繁体   English   中英

为什么我不能将这从Monad推广到Applicative?

[英]Why can't I generalize this from Monad to Applicative?

我概括hoistFree免费hoistFreeM ,类似于如何一个可以概括fmapData.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

不过,我不认为有一种方法可以进一步概括它与任何工作Applicative ,类似于一个如何推广Data.Traversable.mapMData.Traversable.traverse 我对么? 如果是这样,为什么?

你不能通过免费Monad解除Applicative,因为Monad结构需要选择(via (>>=)join ),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层转换为g层,同时生活在v层下面。 由于v是一个Functor ,因此很容易得到v ,但是我们必须将fa转换为ga的唯一方法是我们的​​参数函数forall a . fa -> v (ga) forall a . fa -> v (ga)

我们可以尝试将该fFree包装一起应用以折叠我们的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因此为了包裹它们我们需要以某种方式joinbind

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM