Haskell 为什么可以';我不能把它从Monad推广到Applicative吗?
我将包中的内容概括为Haskell 为什么可以';我不能把它从Monad推广到Applicative吗?,haskell,monads,applicative,Haskell,Monads,Applicative,我将包中的内容概括为winghfreem,类似于将fmap概括为Data.Traversable.mapM import Control.Monad import Control.Monad.Free import Data.Traversable as T hoistFreeM :: (Traversable g, Monad m) => (forall a. f a -> m (g a)) -> Free f b -> m (Free g
winghfreem
,类似于将fmap
概括为Data.Traversable.mapM
import Control.Monad
import Control.Monad.Free
import Data.Traversable as T
hoistFreeM :: (Traversable g, Monad m) =>
(forall a. f a -> m (g a)) -> Free f b -> m (Free g b)
hoistFreeM f = go
where go (Pure x) = return $ Pure x
go (Free xs) = liftM Free $ T.mapM go =<< f xs
import-Control.Monad
进口管制,不含单子
导入数据。可作为T进行遍历
(可遍历的g,单子m)=>
(对于所有a.f a->m(g a))->自由f b->m(自由g b)
提升自由度f=go
where go(Pure x)=返回$Pure x
go(Free xs)=liftM Free$T.mapM go=您无法通过免费的Monad提升应用程序,因为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
我们可以在这里通过类比继续mapM
变成TRAVENSE
,我们可以到达
hoistFreeA f (Free xs) = ?f $ traverse (hoistFreeA f) xs
我一直在使用?f
作为一个临时类型的孔,试图找出如何前进。我们可以完成这个定义,如果我们能够
?f :: v (f (Free g b)) -> v (Free g b)
换句话说,我们需要将f
层转换为g
层,同时生活在v
层之下。由于v
是一个函子
,因此很容易理解v
,但我们必须将fa
转换为ga
的唯一方法是对所有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)
这只是加入,所以我们被卡住了。从根本上说,这是我们永远会陷入困境的地方。自由单子模型单子,因此为了将其封装,我们需要以某种方式加入
或绑定
你的意思是将单子m
推广到应用m
,还是可遍历g
到应用g
?我明白是什么立即阻止了我编写函数。我更感兴趣的是关于为什么会发生这种情况的一些理论。你说“自由单子模型单子,因此为了封装它们,我们需要某种方式join
或bind
”,这基本上符合我自己的直觉猜测,但这并不能帮助我理解为什么,例如,我可以编写traverseFree::(Applicative f,Traversable g)=>(a->fb)->自由ga->f(Free gb)
,但不是freea::(可遍历的g,应用的h)=>(对于所有的a.f a->h(ga))->Free f b->h(Free g b)
。您需要对输入的Free
monad的底层Functor
施加可遍历的约束。如果你注意到的话,这就是traverseFree
的位置。我能做的最好的理论讨论就是比较不同的Free
树的形状。因为自由单子和应用程序都是初始的,我们知道我们可以使用它们作为模型来讨论这两个类别之间的映射Free
Monad通过函子合成构建它们的树,而FreeAp
应用程序通过产品来构建它们的树。如果您所拥有的只是从源函子到目标函子的自然转换(包装在applicative中),那么您不能通过没有join
的函子组合来应用“向下”,但您可以遍历(,)
。我不确定您对可遍历约束的评论是什么意思。Traversable
约束位于两个函数中输出Free
单子的底层Functor
。也许这就是你的意思。啊,我现在明白了。函子合成是原因。
?f :: v (v (Free g b)) -> v (Free g b)