微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么没有ParsecT的MonadWriter实例?

如何解决为什么没有ParsecT的MonadWriter实例?

我今天早些时候在写一些Haskell。提出了类似

方法
{-# LANGUAGE GeneralizednewtypeDeriving #-}

newtype Foo a = Foo { ParsecT String () (Writer DefinitelyAMonoid) a }
    deriving (Functor,applicative,Monad,MonadWriter DefinitelyAMonoid)

这没有编译。 GHC告诉我:“ (MonadWriter DefinitelyAMonoid (ParsecT String () (Writer DefinitelyAMonoid)))的任何实例都不来自数据类型声明的'deriving'子句。”因此,我决定看看其他一些MTL类是否也可以工作。 ReaderMonadReader,以及WriterMonadWriter。因此,我由不和谐用户 turned 定向到Hackage,问题很明显:

MonadState  s m => MonadState  s (ParsecT s' u m)
MonadReader r m => MonadReader r (ParsecT s  u m)
MonadError  e m => MonadError  e (ParsecT s  u m)

没有MonadWriter实例可以通过ParsecT转换器实现!在我看来,这对世界来说就像是一个监督,而在Github上发布问题之前,我几乎没有意识到这可能是故意的。所以我看了Megaparsec

(Stream s,MonadState st m) => MonadState st (ParsecT e s m)
(Stream s,MonadReader r m) => MonadReader r (ParsecT e s m)
(Stream s,MonadError e' m) => MonadError e' (ParsecT e s m)

再次,没有MonadWriter

为什么Parsec和Megaparsec都不提供MonadWriter的{​​{1}}实例?这样的解析器monad是否有与众不同之处,以免它们与作家打成一片?是否有类似this的事情发生?

解决方法

Parsec是回溯单子。尽管您提出的MonadWriter实例并非不可能,但将Writer放在回溯单子下面是一件奇怪的事情。这是因为monad堆栈的内层提供了外层构建的“基础”效果-也就是说,无论ParsecT u (Writer w)做什么,它都必须仅根据 tell。因此,如果tell是分支中的某个值,后来又回溯到该分支中,则不可能“解开”该值,因此Writer的结果将更像是解析算法,而不是解析Parsec呈现的数据流抽象。它不是没有用,但很奇怪,如果WriterT位于外部而Parsec位于内部,则语义会更加自然。

同一论点适用于State。 Parsec公开了它自己的用户状态功能(u参数)和一个继承基础monad状态功能的MonadState实例。后者具有与MonadWriter相同的警告-有状态性遵循算法的轨迹,而不是数据流。我不知道为什么不包含Writer实例却包含此实例;它们都以相同的方式很棘手。

-- I'm presuming the user might want a separate,non-backtracking
-- state aside from the Parsec user state.
instance (MonadState s m) => MonadState s (ParsecT s' u m) where
    get = lift get
    put = lift . put
另一方面,

Parsec的用户状态遵循数据流而不是计算,并且其效果与在外部放置StateT相同。 Parsec提供自己的状态功能而不是仅仅要求我们使用变压器似乎总是很奇怪-但是,现在考虑一下,我怀疑这是为了避免必须lift放在各处确实使用状态。

总而言之,他们可以提供您要求的MonadWriter实例,但我认为有充分的理由不-阻止犯下我认为您可能犯的错误。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?