繁体   English   中英

Haskell的FreeT和Coroutine类型之间有什么关系

[英]what is the relationship between Haskell's FreeT and Coroutine type

Monad.Reader Issue 19中的“Coroutine Pipelines”文章中,作者定义了一个通用的Coroutine类型:

newtype Coroutine f m a = Coroutine
  { resume :: m (Either (f (Coroutine f m a)) a)
  }

我注意到这种类型与free软件包中的FreeT类型非常相似:

data FreeF f a b = Pure a | Free (f b)

newtype FreeT f m a = FreeT
  { runFreeT :: m (FreeF f a (FreeT f m a))
  }

似乎FreeTCoroutine是同构的。 以下是从一个映射到另一个的函数:

freeTToCoroutine
  :: forall f m a. (Functor f, Functor m) => FreeT f m a -> Coroutine f m a
freeTToCoroutine (FreeT action) = Coroutine $ fmap f action
  where
    f :: FreeF f a (FreeT f m a) -> Either (f (Coroutine f m a)) a
    f (Pure a) = Right a
    f (Free inner) = Left $ fmap freeTToCoroutine inner

coroutineToFreeT
  :: forall f m a. (Functor f, Functor m) => Coroutine f m a -> FreeT f m a
coroutineToFreeT (Coroutine action) = FreeT $ fmap f action
  where
    f :: Either (f (Coroutine f m a)) a -> FreeF f a (FreeT f m a)
    f (Right a) = Pure a
    f (Left inner) = Free $ fmap coroutineToFreeT inner

我有以下问题:

  1. FreeTCoroutine类型之间有什么关系? 为什么“Coroutine Pipelines”的作者不使用FreeT类型而不是创建Coroutine类型?
  2. 免费monad和协同程序之间是否存在某种更深层次的关系? 类型是同构的似乎并不是巧合。
  3. 为什么Haskell中流行的流媒体库不是基于FreeT

    pipes的核心数据类型是Proxy

     data Proxy a' ab' bmr = Request a' (a -> Proxy a' ab' bmr ) | Respond b (b' -> Proxy a' ab' bmr ) | M (m (Proxy a' ab' bmr)) | Pure r 

    conduit的核心数据类型是Pipe

     data Pipe lioumr = HaveOutput (Pipe lioumr) (m ()) o | NeedInput (i -> Pipe lioumr) (u -> Pipe lioumr) | Done r | PipeM (m (Pipe lioumr)) | Leftover (Pipe lioumr) l 

    我想可以编写基于FreeTProxyPipe数据类型,所以我想知道它为什么没有完成? 是出于性能原因吗?

    我在流行的流媒体库中看到的FreeT的唯一提示是pipes-group ,它使用FreeT中的项目进行分组。

要回答你的第二个问题,让我们首先通过查看Free简化问题。 Free fa允许你构造a f形AST,以便以后减少(也就是说,解释)。 当比较文章中的monad变换器与未提升的自由构造时,我们可以简单地选择Identity for m ,这是从变换器构造基monad的通常做法: Free f = FreeT Identity f

Monad Reader的文章首先介绍了一个提升的Trampoline Monad变换器,所以让我们首先看一下未提升的版本,其中Identity被删除:

data Trampoline a = Return a | Bounce (Trampoline a)

如果我们将此与Free进行比较

data Free f r = Pure r | Free (f (Free f r))

稍微斜视一下,我们可以看到我们真正需要做的就是“移除” f结构,就像我们之前“移除” m结构一样。 所以,我们有Trampoline = Free Identity ,因为Identity没有结构。 反过来,这意味着这个蹦床是一个FreeT Identity Identity :一种简单的FreeT Identity Identity协程,无法使用效果确定是否反弹或返回。 这就是这个蹦床和蹦床monad变压器之间的区别:变压器允许弹跳与m -actions交错。

通过一些工作,我们还可以看到生成器和消费者是f特定选择的免费monad,分别是((,) a)((->) a) 他们的免费monad变换器版本同样允许它们交错m -actions(例如,发生器可以在屈服之前请求用户输入)。 Coroutine概括两者f中,AST形状(固定为f ~ Identity用于蹦床)和其可交错效果的类型(固定为无影响,或m ~ Identity )为Free 这正是FreeT mf

直觉上,如果Free f是用于构造f形AST的monad那么FreeT mf是用于构造与m提供的效果交错的f形AST的monad。 如果你稍微眯一下,这正是协同程序的完整概括:在构造的AST的形状和用于构造它的效果类型上参数化计算的计算。

暂无
暂无

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

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