Почему компилятор не может вывести тип Functor в примерах Free Applicative?

module Main where

data Toy b next =
    Output b next
  | Bell next
  | Done

data FixE f e = Fix (f (FixE f e)) | Throw e

-- The working monadic function
catch :: (Functor f) => FixE f e1 -> (e1 -> FixE f e2) -> FixE f e2
catch (Fix x) f = Fix (fmap (`catch` f) x)
catch (Throw e) f = f e

-- Type error
applicate_fixe :: (Functor f) => FixE f (e1 -> e2) -> FixE f e1 -> FixE f e2
applicate_fixe a b = a `catch` (`fmap` b)

-- Type error
applicate_fixe' :: (Functor f) => FixE f (e1 -> e2) -> FixE f e1 -> FixE f e2
applicate_fixe' (Throw f) b = fmap f b
applicate_fixe' (Fix f) b = Fix (fmap (`applicate_fixe` b) f)

main :: IO()
main = print "Hello."

C:\!Various_Exercises\Haskell_Exercises\Free_Monad_Stuff\test.hs: 15, 33
Could not deduce (Functor (FixE f)) arising from a use of `fmap'
from the context (Functor f)
  bound by the type signature for
             applicate_fixe :: Functor f =>
                               FixE f (e1 -> e2) -> FixE f e1 -> FixE f e2
  at test.hs:14:19-76
In the second argument of `catch', namely `(`fmap` b)'
In the expression: a `catch` (`fmap` b)
In an equation for `applicate_fixe':
    applicate_fixe a b = a `catch` (`fmap` b)
C:\!Various_Exercises\Haskell_Exercises\Free_Monad_Stuff\test.hs: 18, 31
Could not deduce (Functor (FixE f)) arising from a use of `fmap'
from the context (Functor f)
  bound by the type signature for
             applicate_fixe' :: Functor f =>
                                FixE f (e1 -> e2) -> FixE f e1 -> FixE f e2
  at test.hs:17:20-77
In the expression: fmap f b
In an equation for applicate_fixe':
    applicate_fixe' (Throw f) b = fmap f b

Я перехожу к этому руководству, пытаясь чтобы выяснить свободную монаду, и в качестве упражнения я также пытаюсь выполнить аппликативную функцию. Честно говоря, я не уверен, что эти ошибки должны означать.

Также я не уверен, какой именно должна быть сигнатура типа для data FixE f e = Fix (f (FixE f e)) | Throw e. Сначала я подумал, что f (FixE f e) должен быть кортежем, но похоже, что это один аргумент, поэтому часть (FixE f e) на самом деле является аргументом типа для первого f. Но если это так, не должен ли f внутри FixE f e также требовать аргумента типа?

Редактировать:

applicate_fixe :: (Functor f) => FixE f (e1 -> e2) -> FixE f e1 -> FixE f e2
applicate_fixe (Fix f) b = Fix (fmap (`applicate_fixe` b) f) -- Works as the f argument in fmap is a functor
applicate_fixe (Throw f) (Fix b) = fmap f b -- The b is of type f (FixE f e1) so it is clearly a functor and yet the type system rejects it.

Прежде всего, я не понимаю эту последнюю часть. Также, что именно должно иметь экземпляр функтора? f должно уже иметь это ограничение в приведенном выше определении.

Edit2: Возможно, вы имеете в виду, что FixE должен иметь экземпляр Functor.

instance Functor f => Functor (FixE f) where
  fmap f (Fix x) = fmap f x -- Type error
  fmap f (Throw e) = Throw (f e)

Вот мой лучший снимок, но он жалуется, что тип f слишком жесткий в первой строке.


person Marko Grdinic    schedule 30.09.2016    source источник
comment
Вам нужно определить фактический экземпляр Functor для использования fmap. Вы уже определили >>= для FixE f, а return — это ThrowE, поэтому вы можете использовать реализации по умолчанию для Functor и Applicative.   -  person user2407038    schedule 30.09.2016
comment
Я не думаю, что это то, о чем ошибка типа. Что ж, теперь я вроде как понимаю, что они означают, но что меня действительно удивляет, так это то, что когда я меняю applicate_fixe'' (Throw f) b = fmap f b на applicate_fixe' (Throw f) (Fix b) = fmap f b, я все еще получаю ошибку типа. Это сбивает с толку, потому что b в Fix b действительно является функтором, но компилятор все еще не примет его.   -  person Marko Grdinic    schedule 30.09.2016
comment
Вам нужно либо добавить instance .. => Functor (...) where fmap = ... явно, либо использовать механизм deriving (возможно, автономный). Если вы этого не сделаете, Haskell не снабдит ваш тип каким-либо экземпляром (ни для Functor, ни для Eq, Show, ... или любого другого класса).   -  person chi    schedule 30.09.2016
comment
@chi, ну, вы получаете два нестандартных класса бесплатно с достаточно новыми компиляторами. Typeable и Coercible не нужно выводить явно.   -  person dfeuer    schedule 30.09.2016
comment
Пожалуйста, смотрите редактирование.   -  person Marko Grdinic    schedule 01.10.2016
comment
@melpomene Нет, это все еще дает мне ошибки типа.   -  person Marko Grdinic    schedule 01.10.2016
comment
Разве это не должно быть fmap f (Fix x) = Fix (fmap (fmap f) x)?   -  person melpomene    schedule 01.10.2016
comment
@melpomene Да, это так. Не видел, что один идет. Также изменение applicate_fixe (Throw f) (Fix b) = fmap f b на applicate_fixe (Throw f) b = fmap f b теперь исправляет ошибку типа. Я предполагаю, что у меня есть мой applicative прямо здесь.   -  person Marko Grdinic    schedule 01.10.2016


Ответы (1)


module Main where

data Toy b next =
    Output b next
  | Bell next
  | Done

instance Functor f => Functor (FixE f) where
  fmap f (Fix x) = Fix (fmap (fmap f) x)
  fmap f (Throw e) = Throw (f e)

data FixE f e = Fix (f (FixE f e)) | Throw e

-- Monadic function
catch :: (Functor f) => FixE f e1 -> (e1 -> FixE f e2) -> FixE f e2
catch (Fix x) f = Fix (fmap (`catch` f) x)
catch (Throw e) f = f e

-- Applicative function
applicativeFixE :: (Functor f) => FixE f (e1 -> e2) -> FixE f e1 -> FixE f e2
applicativeFixE (Fix f) b = Fix (fmap (`applicativeFixE` b) f)
applicativeFixE (Throw f) b = fmap f b

main :: IO()
main = print "Hello."

На основе комментариев мне удалось реализовать аппликативную функцию. Я не совсем уверен, почему приведенное выше работает по сравнению с некоторыми альтернативами, которые я пробовал, но он проверяет тип.

Всем спасибо.

person Marko Grdinic    schedule 01.10.2016