Free モナドを介して Applicative を持ち上げることはできません。Monad 構造が ((>>=)
またはを介してjoin
) 選択を要求し、Applicative がそれを提供できないためです。しかし、おそらく当然のことながら、Free Applicative を介して Applicative を持ち上げることができます。
-- also from the `free` package
data Ap f a where
Pure :: a -> Ap f a
Ap :: f a -> Ap f (a -> b) -> Ap f b
hoistAp :: (forall a. f a -> g a) -> Ap f b -> Ap g b
hoistAp _ (Pure a) = Pure a
hoistAp f (Ap x y) = Ap (f x) (hoistAp f y)
hoistApA :: Applicative v => (forall a. f a -> v (g a)) -> Ap f b -> v (Ap g b)
hoistApA _ (Pure a) = pure (Pure a)
hoistApA f (Ap x y) = Ap <$> f x <*> hoistApA f y
-- just what you'd expect, really
より明確にするために、 に一般化してみましょhoistFreeM
うhoistFreeA
。始めるのはとても簡単です
hoistFreeA :: (Traversable f, Applicative v) =>
(forall a. f a -> v (g a)) -> Free f b -> v (Free g b)
hoistFreeA _ (Pure a) = pure (Pure a)
そして、ここから類推によって続けることができhoistFreeM
ます。mapM
となりtraverse
、私たちはどこまでもたどり着くことができます
hoistFreeA f (Free xs) = ?f $ traverse (hoistFreeA f) xs
?f
前進する方法を見つけようとして、その場しのぎのタイプの穴として使用してきた場所. できる場合、この定義を完成させることができます。
?f :: v (f (Free g b)) -> v (Free g b)
つまり、レイヤーの下に住みながら、そのf
レイヤーをレイヤーに変換する必要があります。は であるため、下に移動するのは簡単ですが、変換する必要がある唯一の方法は、引数の functionです。g
v
v
v
Functor
f a
g a
forall a . f a -> v (g a)
とにかく、レイヤーを折り畳むためにラッパーf
と一緒にそれを適用してみることができます。Free
g
hoistFreeA f (Free xs) = ?f . fmap (fmap Free . f) $ traverse (hoistFreeA f) xs
しかし今、私たちは解決しなければなりません
?f :: v (v (Free g b)) -> v (Free g b)
これは単にjoin
であるため、行き詰まっています。これは基本的に、私たちが常に立ち往生する場所です。Free Monads は Monads をモデル化しているため、Monads をラップするには何らかの方法でjoin
or bind
.