由於Monad結構要求選擇(通過(>>=)
或join
),並且Applicative無法提供該選項,因此無法通過Free Monad提升應用程序。但是,也許並不奇怪,你可以通過一個免費應用型
-- 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
層轉變爲g
層,而生活在我們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
,所以我們就完蛋了。這基本上是我們總是陷入困境的地方。免費Monads模型Monads,因此爲了包裝它們,我們需要以某種方式join
或bind
。
你的意思是將'Monad m'概括爲'Applicative m',或'Traversable g'概括爲'Applicative g'? –
我的意思是前者。 –