Я думаю, что я придумала интересный "быстрый" экземпляр Applicative
Free
.
data FreeMonad f a = Free (f (FreeMonad f a))
| Return a
instance Functor f => Functor (FreeMonad f) where
fmap f (Return x) = Return (f x)
fmap f (Free xs) = Free (fmap (fmap f) xs)
instance Applicative f => Applicative (FreeMonad f) where
pure = Return
Return f <*> xs = fmap f xs
fs <*> Return x = fmap ($x) fs
Free fs <*> Free xs = Free $ liftA2 (<*>) fs xs
Это своего рода самая длинная стратегия. Например, используя data Pair r = Pair rr
в качестве функтора (поэтому FreeMonad Pair
представляет собой двоичное дерево с внешней меткой):
+---+---+ +---+---+ +-----+-----+
| | | | <*> | |
+--+--+ h x +--+--+ --> +--+--+ +--+--+
| | | | | | | |
f g y z f x g x h y h z
Я не видел, чтобы кто-нибудь упоминал этот случай раньше. Это нарушает какие-либо Applicative
законы? (Конечно, это не согласуется с обычным экземпляром Monad
, который является "заменой", а не "молниеносным".)