Haskell 99题第6题isPalindromeM实现所使用的Monad类型咨询
问题解答
你提到的这段回文判断代码里用到的不是List Monad,而是函数Monad(即((->) r)类型的Monad实例,也是Reader Monad的基础实现)。
类型推导验证
我们可以通过>>=的类型签名一步步验证匹配逻辑:
- Monad绑定操作
>>=的通用类型为:Monad m => m a -> (a -> m b) -> m b - 代码中
>>=左侧的reverse类型为:[c] -> [c] - 代码中
>>=右侧的(==)类型为:Eq c => [c] -> ([c] -> Bool)
把上述类型套入>>=的签名就能匹配到:这里的Monad实例m就是((->) [c]),也就是「接收参数类型为[c]的函数」的类型构造器:
- 对应
m a的部分:((->) [c]) [c]等价于[c] -> [c],完全匹配reverse的类型 - 对应
(a -> m b)的部分:[c] -> ((->) [c]) Bool等价于[c] -> [c] -> Bool,完全匹配(==)的类型 - 最终返回的
m b类型为((->) [c]) Bool,等价于[c] -> Bool,和函数定义的签名完全一致。
实现逻辑展开
((->) r)类型的Monad实例中,>>=的具体实现规则为:
(f >>= g) x = g (f x) x
把代码中的f替换为reverse,g替换为(==),就能直接展开得到普通写法的回文判断逻辑:
isPalindromeM xs = (==) (reverse xs) xs -- 等价于更常见的写法: isPalindrome xs = xs == reverse xs
为什么不是List Monad?
List Monad的作用对象是列表值,其>>=的逻辑是遍历列表的每个元素,传入后续函数处理后把所有返回的列表拼接成最终结果,和这里的函数式参数传递逻辑完全无关,所以不是你最初猜测的List Monad。
内容的提问来源于stack exchange,提问作者Anthony D'Arienzo
相关产品推荐
相关产品推荐

