11

我试图将IResult单子从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

(当你使用它时,它的名字来自Danielsson 的一篇论文Partiality ()

我可以Partiality用作基本单子,但是有PartialityT单子转换器吗?

4

1 回答 1

12

肯定有!你的Partialitymonad 是一个免费的 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 中的操作。我们免费获得MonadandMonadTrans实例PartialityT,因为免费的 monad 转换器自动成为任何给定函子的 monad 和 monad 转换器。

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

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

我建议你阅读我写的关于免费 monad 转换器的这篇文章。但是,免费的 monad 转换器的新官方主页是free包。

此外,如果您正在寻找有效的增量解析器,我将pipes-parse在几天内将其作为软件包发布。您可以在此处查看当前草稿

于 2013-03-04T04:18:13.143 回答