#haskell #applicative #free-monad
#haskell #аппликативный #free-monad
Вопрос:
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_ExercisesHaskell_ExercisesFree_Monad_Stufftest.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_ExercisesHaskell_ExercisesFree_Monad_Stufftest.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
inside 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
это ограничение уже должно быть указано в приведенном выше определении.
Редактирование 2: Может быть, вы имеете в виду, что у FixE должен быть экземпляр функтора.
instance Functor f => Functor (FixE f) where
fmap f (Fix x) = fmap f x -- Type error
fmap f (Throw e) = Throw (f e)
Вот мой лучший снимок, но он жалуется, что тип f слишком жесткий в первой строке.
Комментарии:
1. Вам нужно определить фактический экземпляр
Functor
для использованияfmap
. Вы уже определили>>=
дляFixE f
иreturn
ThrowE
, поэтому вы можете использовать реализации по умолчанию дляFunctor
иApplicative
.2. Я не думаю, что это ошибка типа. Ну, я вроде понимаю, что они имеют в виду сейчас, но что меня действительно удивляет, так это то, что при изменении
applicate_fixe'' (Throw f) b = fmap f b
наapplicate_fixe' (Throw f) (Fix b) = fmap f b
я все равно получаю ошибку типа. Это сбивает с толку, потомуb
что inFix b
действительно является функтором, и все же компилятор по-прежнему не принимает его.3. Вам нужно либо добавить
instance .. => Functor (...) where fmap = ...
явно, либо использоватьderiving
механизм (возможно, автономный). Если вы этого не сделаете, Haskell не предоставит вашему типу ни одного экземпляра (ни дляFunctor
, ни дляEq
,Show
, … , ни для любого другого класса).4. @chi, ну, вы получаете два нестандартных класса бесплатно с достаточно новыми компиляторами.
Typeable
иCoercible
не нужно выводить явно.5. Пожалуйста, посмотрите редактирование.
Ответ №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."
На основе комментариев мне удалось реализовать прикладную функцию. Я не совсем уверен, почему приведенное выше работает по сравнению с некоторыми альтернативами, которые я пробовал, но он проверяет тип.
Спасибо всем.