“数据类型点菜”与嵌套的FreeT变换器

时间:2014-01-28 20:51:33

标签: haskell monads

this question的评论中,已经提到嵌套多层FreeT变换器(每个变换器都有不同的仿函数)可以实现与"Data types à la carte"方法类似的目的(尽管两种方法不同构,但是使用副产品组合了仿函数本身。

我的问题是:差异在哪里?是否存在一种方法可以处理的情况,而不是另一种方法?他们是否承认不同的口译员?

更新:以下是嵌套FreeT变换器的简单示例。通过发出日志消息和请求延迟的能力来扩充计算:

import Data.Functor.Identity
import Control.Monad
import Control.Monad.Trans
import Control.Monad.Trans.Free
import Control.Concurrent

type Delay = Int

type DelayT = FreeT ((,) Delay)

delay ::  Monad m => Delay -> DelayT m ()
delay t = liftF (t,()) 

type Message = String

type LogT = FreeT ((,) Message)

emitLog :: Monad m => Message -> LogT m ()
emitLog msg = liftF (msg,()) 

type Effected = DelayT (LogT Identity)

program :: Effected Char
program = lift (emitLog "foo") >> delay 1000 >> return 'c'

interpret :: Effected a -> IO a 
interpret =                          (iterT $ \(d,a)->threadDelay d >> a)  
            . hoistFreeT             (iterT $ \(m,a)->putStrLn m >> a) 
            . hoistFreeT (hoistFreeT (return . runIdentity))

main :: IO ()
main = interpret program >>= putChar  

(通过使用Producer包中的pipes s,这个特殊的例子可以更简单,这是一种特殊的免费monad变换器。)

1 个答案:

答案 0 :(得分:5)

我对自己对此的理解并不是100%自信,所以如果有人注意到任何(公然)错误,请指出。

从可扩展效果开始,Eff类型与...基本同构:

data Eff :: [* -> *] -> * -> * where
    Pure :: a -> Eff es a
    Side :: Union es (Eff es a) -> Eff es a

其中Union es a是由es参数化的类型列表a的联合/和类型。 Union与来自单一数据类型的:+:的重复应用同构。为了总结(!),Eff似乎是数据类型的优化版本。

我们可以得出结论,本文描述的monad变换器和可扩展效应之间的差异适用于此处。特别是,自由monad变换器堆栈不能交错效果,而数据类型单点/可扩展效果可以。