Haskell中用于isPalindrome的monad

8
第6个Haskell问题是99个Haskell问题中的一个,可以在wiki.haskell.org上找到解决方案。该问题提供了一种单子测试列表(类型为[a])是否为回文的方法:
isPalindromeM :: (Eq a) => [a] -> Bool
isPalindromeM = reverse >>= (==)

(这里的reverse :: [c] -> [c]接受一个列表并以相反的顺序输出一个列表)。

绑定操作意味着这里涉及到一个单子,但是这个单子是什么?

由于isPalindrome涉及到列表,我的第一个猜想是单子与List单子相关,但我不知道如何建立联系。


2
函数具有适用/单子实例。但我看不出使用单子实例而不是应用实例的理由(除了省略flip)。所以我会问作者,为什么不使用isPalindromA = (==) <*> reverse - Micha Wiedenmann
@Micha 我完全同意,特别是因为我发现应用形式更加透明。我的问题更多地针对“为什么这个单子表达式有效?” - Anthony D'Arienzo
1个回答

10

我花了一些时间才找到单子,由于它与List无关,所以我决定发布一个答案。

表达式reverse >>= (==)意味着reverse的类型是m a,其中m是某个单子,因此m a是类型[c] -> [c]。我们还需要isPalindromeM的类型为[c] -> Bool,并且绑定表达式暗示m b[c] -> Bool相同。最后,这个上下文要求(==)::[c]-> [c]->Bool的类型为a -> m b

因此我们得出结论a[c]bBool,单子m接受类型a并将其发送到函数类型[c] -> a。这表明正在使用的单子是Monad ((->) [c])在此定义

如果这个故事有一些道德,也许就是“你可以从任何东西中制作一个单子”。


2
基本上没错,但我想指出的是,Monad实例在技术上是((->) [c]),即已经专门化为r ~ [c]((->) r)是任何r的Monad,在你的情况下,r[c] - amalloy
2
检查代码是否使用列表单子的一种方法是检查 (>>=) 中“发送”了什么。在您的情况下,是 reverse >>= ...。由于 reverse 不是一个列表,因此这不是列表单子。 - Micha Wiedenmann

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接