【问题标题】:Haskell monad for isPalindromeisPalindrome 的 Haskell 单子
【发布时间】:2021-12-24 10:18:59
【问题描述】:

wiki.haskell.org 上的 99 个 Haskell 问题中的第 6 个提出了一种测试列表([a] 类型)是否为回文的单子方法:

isPalindromeM :: (Eq a) => [a] -> Bool
isPalindromeM = reverse >>= (==)

(这里reverse :: [c] -> [c] 接受一个列表并按倒序输出一个列表)。

绑定操作意味着这里有一个 monad,但是这个 monad 是什么?

由于 isPalindrome 涉及列表,我的第一个猜测是 monad 与 List 相关,但我不知道如何绘制连接。

【问题讨论】:

  • Functions have an applicative/monad instance。但我认为没有理由在应用程序上使用 monad 实例(除了删除flip)。所以我想问问作者,为什么不isPalindromA = (==) <*> reverse
  • @Micha 我完全同意,尤其是因为我发现应用形式更加透明。我的问题更多地针对“为什么这种单子表达式有效?”

标签: haskell monads


【解决方案1】:

我花了一些时间才找到 monad,由于它与 List 无关,我想我会发布一个答案。

表达式reverse >>= (==) 暗示reverse 的类型是m a,对于某些monad m,因此m a[c] -> [c] 类型。我们还需要isPalindromeM 具有[c] -> Bool 类型,并且绑定表达式意味着m b[c] -> Bool 相同。最后,此上下文要求 (==) :: [c] -> [c] -> Bool 具有 a -> m b 类型。

因此我们推断a[c]bBool,并且monad m 接受一个类型a 并将它发送到函数类型[c] -> a。这表明起作用的单子是Monad ((->) [c])defined here

如果这个故事有什么寓意的话,也许是“你可以用任何东西制作一个单子”。

【讨论】:

  • 基本上是对的,但我会说 monad 实例在技术上是 ((->) [c]),即它已专门用于 r ~ [c]((->) r) 是任何 r 的单子,在您的情况下,r[c]
  • 检查一段代码是否使用 list monad 的一种方法是检查什么是“发送”到(>>=)。在你的情况下reverse >>= ...。由于reverse 不是列表,因此这不是列表单子。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多