从验证(https://hackage.haskell.org/package/Validation)的示例中,我试图直观地了解如何/为什么申请人不能成为Monad(Why can AccValidation not have a Monad instance?)
你能挑战我的推理吗?
我认为我们处理联接背后的方式(m(m b) - > m b),让我们通过验证这样的例子来理解我的理解:
在data Validation err a
中,仿函数结构是(验证错误)。当您查看Monad的bind定义并专门化验证类型时,您将获得以下内容:
(>>=) :: m a -> (a -> m b) -> m b
(>>=) :: (Validation err) a -> ( a -> (Validation err) b) -> (Validation err) b
如果你缩小(>> =),你会得到:
m a -> (a -> m b) -> m b // if we apply (m a) in the monadic function
m ( m b) -> m b
然后得到(>> =)的结果是m b,你将使用join:
join :: (Monad m) => m (m a) -> m a
join x = x >>= id
如果您使用的类型为:
join m ( m b ) = m ( m b) >>= (\(m b) -> m b -> m b) which gives m b
因此,只需删除最外层结构,只保留/传递最内层类型中的值(最里面的函子的值)。
在monad中,我们无法将仿函数结构中的一些信息(例如验证错误)传递给下一个“动作”,我们唯一能想到的就是值。您可以对该结构进行唯一的考虑是将序列短路以从中获取信息。
您无法对仿函数结构中的信息执行一系列操作(例如,累积类似错误的内容......)
所以我会说,一个在其结构上用一些逻辑压缩其结构的应用程序可能会因为无法成为Monad而产生怀疑?
答案 0 :(得分:0)
这不是一个真正的答案,但评论的时间太长了。
This以及该主题中的其他引用讨论是相关的。我认为这个问题是倒退的:所有Monad
s自然会产生Applicative
(其中pure = return
等);问题是大多数用户期望/假设(类型为实例Monad
) Applicative
实例在语义上等同于Monad引发的实例。 / p>
这在Applicative
课程中被记录为一种法律,但我并不完全相信它是合理的。这个论点似乎是让Applicative
和Monad
以这种方式达成一致是令人困惑的。
我使用Validation
的经验是,做任何大事都是噩梦,因为符号变得一团糟,而且你发现你有一些数据依赖(例如你需要解析和验证)一节基于前一节的解析)。您最终定义bindV
,其行为类似于Error
monad >>=
,因为正确的Monad
实例被视为可疑。
然而,使用这样的Monad
/ Applicative
对可以满足您的需求:特别是在使用ApplicativeDo
时(我想;还没试过这个),效果如下以Monadic风格编写解析器(例如)是基于解析代码的数据依赖性,您可以在每个级别累积尽可能多的错误。 Haxl
可以说可以捏造这个"法律"以类似的方式。
我没有足够的经验使用Applicative
而不是Monad
的其他类型,以了解是否有合理的规则来确定它是什么时候?#{1}}没关系"因为申请人以这种方式不同意。也许Validation
似乎合情合理是完全随意的。
我不确定如何直接回答你的问题。我认为你首先要采用Applicative
类文档底部记录的法律,并翻转它们,以便得到:
return = pure
ap m1 m2 = m1 <*> m2
如果ap
是Monad
的方法而且上面是最小的完整定义,那么您只需要测试上述内容是否通过Monad
法律来回答您的问题任何Applicative
的问题,但当然不是这样。