【发布时间】: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