这是又一个通过范畴论来解释 Haskell 的问题。
让我们以一些简单而广为人知的东西为例。fmap?所以,省略了 f 实际上是一个 Functor 这个事实,有
(1) fmap 是一个生成函数的函数。
现在,Hask 也包含函数,所以
(2)
现在奇怪的事情发生了:显然,fmap 是 Hask 的一个态射,因此它是一个函数,它接受另一个函数并将其转换为另一个函数;最终的函数尚未应用。
因此,需要另一个 Hask 的态射才能从
另一种看待它的方式是 GHC 风格:
我想在这一点上问一下:
让我们以一些简单而广为人知的东西为例。fmap?所以,省略了 f 实际上是一个 Functor 这个事实,有
fmap :: (a -> b) -> f a -> f b
。据我所知,(a -> b) -> f a -> f b
只不过是 (a -> b) -> (f a -> f b)
的语法糖;因此得出结论:(1) fmap 是一个生成函数的函数。
现在,Hask 也包含函数,所以
(a -> b)
,特别是 (f a -> f b)
,是 Hask 的一个对象(因为 Hask 的对象是明确定义的 Haskell 类型 - 即数学集合 - 并且确实存在类型为 (a -> b)
的集合,对于每个可能的 a
,对吧?)。所以,再次强调:(2)
(a -> b)
是 Hask 的一个对象。现在奇怪的事情发生了:显然,fmap 是 Hask 的一个态射,因此它是一个函数,它接受另一个函数并将其转换为另一个函数;最终的函数尚未应用。
因此,需要另一个 Hask 的态射才能从
(f a -> f b)
得到 f b
。对于类型为 a
的每个项目 i
,存在一个定义为 \f -> f (lift i)
的态射 apply_i :: (f a -> f b) -> f b
,其中 lift i
是一种构建具有特定 i
的 f a
的方法。另一种看待它的方式是 GHC 风格:
(a -> b) -> f a -> f b
。与我上面写的相反,(a -> b) -> f a
将映射到 Hask 的常规对象。但这种观点违背了 Haskell 的基本公理 - 没有多元函数,只有应用(柯里化)的替代方案。我想在这一点上问一下:
(a -> b) -> f a -> f b
应该是一个 (a -> b) -> (f a -> f b) -> f b
,为了简单起见而使用的语法糖,还是我漏掉了非常、非常重要的东西?