Haskell 哈斯克尔:加入是一种自然的转变吗?

Haskell 哈斯克尔:加入是一种自然的转变吗?,haskell,monads,category-theory,Haskell,Monads,Category Theory,我可以在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是如何自然转换时遇到了一些困难。好的,让我们看看concat 首先,这里是实现: concat ::

我可以在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
是如何自然转换时遇到了一些困难。

好的,让我们看看
concat

首先,这里是实现:

concat :: [[a]] -> [a]
concat = foldr (++) []
这与
h
的结构类似,其中
可能被
[]
取代,更重要的是,
[]
被--to滥用语法--
[[]]
取代

当然,
[[]]
也是一个函子,但它不是自然主义条件使用它的方式的
函子
实例。直接翻译您的示例不起作用:

concat。fmap k
=/=
fmap k。concat

…因为两个
fmap
仅在最外层的
[]
上工作

尽管假定
[[]]
Functor
的一个有效实例,但由于可能显而易见的实际原因,您不能直接将其作为一个实例

但是,您可以重建正确的提升,如下所示:

concat。(fmap.fmap)k
=
fmap k。concat

…其中
fmap。fmap
相当于对
[[]
的假设
函子
实例实现
fmap

作为一个相关的附录,
return
由于相反的原因而显得笨拙:
a->fa
是一个省略的身份函子的自然转换。使用
:[]
可以将标识写为:

(:[])。($)k
=
fmap k。(:[])


…在这里,完全多余的
($)
代替了elided identity函子的
fmap

回答得很好,谢谢。我开始理解
return
的原因是Haskell可能会要求我们使用
i7
I[1,2,3]
等来构造每个值。但这种方法可能有自己的缺点。@user643722:通常很笨拙。否则它是完全等价的,
ia
a
之间的转换是微不足道的。使用显式标识函子的等效方法是对嵌套列表使用
newtype
,例如
newtype L2 a=L2[[a]]
,并将其作为
函子的实例。请记住,
函子
类型类只能描述非常有限的有效函子子集,也就是说,从所有Hask到它的一个子类的函子是由一个单一类型的构造函数定义的
*->*
。是否值得使用
Compose
from
transformers
?这确实让我们为
[[]]
编写了
fmap
的有效定义,如果您将
[[[]]]
编写为
Compose[][]
@ocharles:当然,创建一个包装器来描述函子的组成一直是可能的。这与直接表示函子合成并不完全相同。如果我写
(f.g)
并将其应用于
x
,我不必以某种方式打开结果以获得与
f(gx)
相同的值。令人惊讶的是,由于Reynolds参数,任何看起来像
fa->ga
的合理多态Haskell函数都是一种自然变换(对底部的常见问题进行模化)。这意味着您实际上不必检查每个单独的函数,看看它是否满足自然变换的条件。它们是“自由定理”。开始阅读的地方是: