【问题标题】:How could we know that an applicative can't be a Monad?我们怎么知道应用程序不能是 Monad?
【发布时间】:2018-06-13 18:35:10
【问题描述】:

从验证 (https://hackage.haskell.org/package/Validation) 的示例中,我试图直观地检测应用程序如何/为什么不能是 Monad (Why can AccValidation not have a Monad instance?)

你能挑战我的推理吗?

我想到了我们在连接 (m ( m b) -> m b) 后面处理的方式中的一个 monad,让我们用一个像 Validation 这样的例子来加深我的理解:

data Validation err a 中,函子结构是(Validation err)。当您查看 Monad 的绑定定义并专门为 Validation 指定类型时,您会得到以下信息:

(>>=)  :: m a -> (a -> m b) -> m b
(>>=)  :: (Validation err) a -> (  a -> (Validation err) b) -> (Validation err) b

如果您进行 beta 减少 (>>=),您将获得:

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

所以 join 只是删除最外层的结构,只有最内层类型的值(最内层函子的值)通过序列保持/传输。

在 monad 中,我们不能将函子结构中的某些信息(例如 Validation err)传递给下一个“动作”,我们唯一可以传递的就是值。您可以对这种结构做的唯一想法是短路序列以从中获取信息。

您不能对来自函子结构的信息执行一系列操作(例如,累积类似错误的信息......)

所以我会说,如果应用程序在其结构上使用一些逻辑来压缩其结构,可能会因为无法成为 Monad 而受到怀疑?

【问题讨论】:

  • "So that join 只删除最外层的结构 [...]" -- 在值级别,join 不只是删除外层;它将它与内层合并。
  • 是的,我可以在 Applicative 中看到将 2 个结构压缩在一起的逻辑,但我看不到合并在 Monad 中具体做了什么,这就是为什么我说 drop ..“合并”到目前为止对我来说就像一个黑匣子......
  • 考虑一些具体的例子可能会有所帮助。例如,删除外层对IO 意味着什么?一旦您执行外部IO 计算以“从中获取信息”,就没有回头路——无法撤消或以其他方式丢弃它。
  • 无论如何,这是一个有趣的问题。有关相关讨论,请参阅。 winitzki's answer to Good examples of Not a Functor/Functor/Applicative/Monad?

标签: haskell


【解决方案1】:

这不是一个真正的答案,但评论太长了。

This 和该线程中其他引用的讨论是相关的。我认为这个问题有点倒退:所有Monads 自然会产生Applicative(其中pure = return 等);问题是大多数用户期望/假设(其中类型是实例 MonadApplicative 实例在语义上等同于 Monad 产生的实例

这在Applicative 类中被记录为一种法律,但我并不完全相信它是合理的。这个论点似乎是 ApplicativeMonad 以这种方式不同意是令人困惑的。

我使用Validation 的经验是,用它做任何大事都是一场噩梦,既因为符号变得一团糟,又因为你发现你有一些数据依赖性(例如,你需要根据解析上一节)。你最终定义了bindV,它的行为类似于Error monad >>=,因为正确的Monad 实例被认为是可疑的。

然而使用像这样的Monad/Applicative 对可以满足您的需求:尤其是在使用ApplicativeDo 时(我想;还没有尝试过),在 Monadic 中编写解析器(例如)的效果风格是您可以根据解析代码的数据依赖关系在每个级别累积尽可能多的错误。 Haxl 可以说以类似的方式捏造了这个“法律”。

我对@9​​87654339@ 但不是Monad 的其他类型没有足够的经验,无法知道是否有一个合理的规则可以让Applicative 以这种方式不同意何时“可以”。 Validation 似乎可以正常工作可能完全是武断的。

无论如何...

我不确定如何直接回答您的问题。我认为您首先要了解Applicative 类文档底部记录的法律,然后翻转它们,这样您就会得到:

 return = pure
 ap m1 m2 = m1 <*> m2

如果apMonad 的一种方法,并且上面是一个最小的完整定义,那么您只需测试上面是否通过Monad 法律来回答您对任何Applicative 的问题,但是当然不是这样的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-17
    • 1970-01-01
    • 1970-01-01
    • 2017-02-21
    相关资源
    最近更新 更多