我可以在Haskell中定义一个自然转换:
h :: [a] -> Maybe a
h [] = Nothing
h (x:_) = Just x
并使用函数k:
k :: Char -> Int
k = ord
由于以下事实而满足自然条件:
h . fmap k
== fmap k . h
可以以类似的方式演示List monad的join
函数的自然条件吗?我很难理解join
,特别是concat
是一种自然转换。
答案 0 :(得分:16)
好的,让我们看一下concat
。
首先,这是实施:
concat :: [[a]] -> [a]
concat = foldr (++) []
这与h
的结构相似,其中Maybe
被[]
取代,更重要的是,[]
被 - 替换为 - 暂时滥用语法 - - [[]]
[[]]
也是一个仿函数,但它是不一个Functor
实例,就像自然条件使用它一样。直接翻译您的示例将不起作用:
concat . fmap k
= / = fmap k . concat
...因为fmap
只在最外面的[]
处理。
虽然[[]]
假设是Functor
的有效实例,但由于实际原因可能是显而易见的,因此无法直接将其设为一个。
但是,你可以重建正确的提升:
concat . (fmap . fmap) k
== fmap k . concat
...其中fmap . fmap
相当于fmap
的假设Functor
实例[[]]
的实现。
作为一个相关的附录,return
因为相反的原因而尴尬:a -> f a
是一个来自省略身份仿函数的自然转换。使用: []
身份将被写为:
(:[]) . ($) k
== fmap k . (:[])
...完全多余的($)
代表的是fmap
对于被省略的身份仿函数。