问题 Partiality Monad变压器


我正在试图解构 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 ()

我可以用 Partiality 作为基地monad,但是有一个 PartialityT monad变压器?


7737
2018-03-04 00:55


起源

你的monad实例是什么? Partiality t? - Sjoerd Visscher
添加到主要问题。 - J. Abrahamson


答案:


肯定有!你的 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)

我们用这个构建了免费的monad变换器 await 命令请求新值和 lift 调用基monad中的操作。我们得到了 Monad 和 MonadTrans 实例 PartialityT 免费,因为免费monad变换器自动为任何给定仿函数的monad和monad变换器。

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

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

我建议你看看 这篇文章我写的关于免费monad变形金刚。然而,免费monad变压器的新官方住宅是 free 包。

此外,如果您正在寻找一个有效的增量解析器,我即将发布它作为 pipes-parse 几天内打包。你可以检查一下 目前的草案在这里


12
2018-03-04 04:18



哦,当然是!我的缺点是我无法弄清楚内部monadic层应该在哪里定义 data PartialityT t m a = PT { runPT :: m (Partiality t a) }......它只给我一个内在的monadic层!感谢你向正确的方向推进(以及明显的推广!) - J. Abrahamson
别客气! - Gabriel Gonzalez