【问题标题】:Partiality Monad Transformer偏性单子变压器
【发布时间】:2013-03-04 00:55:43
【问题描述】:

我正在尝试将 IResult monad 从 attoparsec 解构为几部分。这里是IResult

data IResult t r = Fail t [String] String
                 | Partial (t -> IResult t r)
                 | Done t r

这感觉应该是效果、“偏袒”和失败的结合。如果失败仅表示为Either ([String], String),那么偏颇性可能是

data Partiality t a = Now a | Later (t -> Partiality t a)

instance Monad (Partiality t) where
  return = pure
  (Now a) >>= f = f a
  (Later go) >>= f = Later $ \t -> go t >>= f

class MonadPartial t m where
  feed  :: t -> m a -> m a
  final :: m a -> Bool

instance MonadPartial t (Partiality t) where
  feed _ (Now a) = Now a
  feed t (Later go) = go t
  final (Now _) = True
  final (Later _) = False

(当你使用Partiality ()时,它的名字来自a paper by Danielsson

我可以使用 Partiality 作为基本 monad,但是有 PartialityT monad 转换器吗?

【问题讨论】:

  • Partiality t 的 monad 实例是什么?
  • 添加到主要问题中。

标签: haskell monads


【解决方案1】:

肯定有!你的 Partiality monad 是一个免费的 monad:

import Control.Monad.Free  -- from the `free` package

type Partiality t = Free ((->) t)

...而对应的PartialityT是一个免费的monad转换器:

import Control.Monad.Trans.Free  -- also from the `free` package

type PartialityT t = FreeT ((->) t)

这是一个示例程序,展示了您将如何使用它:

import Control.Monad
import Control.Monad.Trans.Class
import Control.Monad.Trans.Free

type PartialityT t = FreeT ((->) t)

await :: (Monad m) => PartialityT t m t
await = liftF id

printer :: (Show a) => PartialityT a IO r
printer = forever $ do
    a <- await
    lift $ print a

runPartialityT :: (Monad m) => [a] -> PartialityT a m r -> m ()
runPartialityT as p = case as of
    []   -> return ()
    a:as -> do
        x <- runFreeT p
        case x of
            Pure _ -> return ()
            Free k -> runPartialityT as (k a)

我们使用await 命令请求新值和lift 调用基本monad 中的操作来构建免费的monad 转换器。我们免费获得PartialityTMonadMonadTrans 实例,因为免费的monad 转换器自动成为任何给定函子的monad 和monad 转换器。

我们像这样运行上面的程序:

>>> runPartialityT [1..] printer
1
2
3
...

我建议你阅读this post I wrote about free monad transformers。但是,免费的 monad 转换器的新官方主页是 free 包。

另外,如果您正在寻找一个有效的增量解析器,我将在几天内将它作为pipes-parse 包发布。您可以查看current draft here

【讨论】:

  • 哦,当然是!我的缺陷是我无法弄清楚内部单子层应该在哪里并定义data PartialityT t m a = PT { runPT :: m (Partiality t a) }...它只给了我一个内部单子层!感谢您朝着正确的方向推动(以及由此产生的明显概括!)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-28
  • 2021-01-25
  • 2011-11-16
  • 2012-02-21
相关资源
最近更新 更多