При попытке найти монашескую монаду, которая может быть выполнена ступенчато/разрешает потоки, я обнаружил свободную монаду
data Free f a = Return a | Roll (f (Free f a))
с его экземпляром монады
instance (Functor f) => Monad (Free f) where
return = Return
Return x >>= f = f x
Roll action >>= f = Roll $ fmap (>>= f) action
и его экземпляр функтора
instance (Functor f) => Functor (Free f) where
fmap f (Return x) = Return (f x)
fmap f (Roll x) = Roll $ fmap (fmap f) x
Я знаю, что каждая монада является аппликативным функтором с pure = return
и (<*>) = ap
.
Для меня аппликативные функторы концептуально сложнее, чем монады. Для лучшего понимания аппликативных функторов мне нравится иметь аппликативный экземпляр, не прибегая к ap
.
Первая строка для <*>
проста:
instance (Applicative f) => Applicative (Free f) where
pure = Return
Return f <*> x = fmap f x -- follows immediately from pure f <*> x = f <$> x
--Roll f <*> x = Roll $ (fmap ((fmap f) <*>)) x -- wrong, does not type-check
Как определить Roll f <*> x
в базовых терминах с помощью fmap
и <*>
?