为什么要为像 `(->) e` 这样的“无名”类型定义一个函数对象实例?

4
在Haskell中,GHC base为类型(->) r定义了一个Functor实例:
instance Functor ((->) r) where
    fmap = (.)

Typeclassopedia解释说,((->) e)是以类型e作为参数的函数的类型。这很有道理,但我不明白与MaybeEither a甚至[]相比,(->) e后来是如何使用的。

我认为我理解了这些函子的定义,它们被命名为:MaybeEither a,但我很难理解一个“无名”的类型(->) r是如何使用的。

这是否意味着我需要怀疑每个类型签名中的任何其他a ->都是函子?这是定义Haskell中箭头->属性的一种方式吗?

这个箭头和类型签名中的箭头是同一个吗,还是来自lambda函数的箭头?我尝试在Haskell报告中查找,但那里使用->作为文档的自己符号,所以没有帮助。

提前感谢任何可以帮助打破(->) r困境的提示。

更新:根据评论,我认为我应该问 -> 类型构造函数定义在哪里?它是内置的吗?
答案是 -> 是内置的,它是一个“函数箭头”或“函数类型构造函数”

4
(->) r 并不是一个匿名类型。实际上,如果你写 a -> b ,你就相当于写了 (->) a b(->) 是一个类型构造器,就像 MaybeEither 等一样。它被用作 "中缀运算符" 并不奇怪。比如 (:) 是一个列表的数据构造器,也被用作中缀运算符。 - Willem Van Onsem
4
它绝不是一个无名之物。它就像其他任何名称一样,只是具有一种有趣的中间语法。((->) r)在任何方面都与Either r没有区别。 - n. m.
4
这是一个内置的功能/选项。 - oisdk
2
一个类型同义词type Arr = (->)会有帮助吗?其中函数的类型是not :: Arr Bool Bool,你提到的实例是instance Functor (Arr a) where fmap :: (b -> b') -> (Arr a b -> Arr a b'); fmap = (.) - Iceland_jack
1
@Iceland_jack,实际上类型同义词确实有助于导航。 - Evgeny
显示剩余2条评论
1个回答

4
(->) r 不是一个匿名类型。它的名称是 (->),就像 Either 一样是一个名称。实际上,如果你写成 a -> b,那么你就写成了 (->) a b。或者如果你写成 a -> b -> c,那么规范形式就是 (->) a ((->) b c)(->) 是一个类型构造器,就像 MaybeEither 等一样。它作为中缀运算符使用并不奇怪。例如,如果你写成 x : xs,那么规范形式就是 (:) x xs(或者更冗长地写成 ((:) x) xs)。如果启用 TypeOperators 扩展,甚至可以像这样写类型:Left 1 :: Int `Either` String

1
这部分特别有用:(->) ((->) a b) c,我认为如果签名可以这样写,那就太好了,而且它确实可以! - Evgeny
1
从学习者的角度来看,人们不会在类型层面上考虑中缀运算符,因此学习起来非常有帮助,再次感谢。 - Evgeny
1
我认为 a -> b -> c 实际上是 (->) a ((->) b c)。它是右结合的。 - Fyodor Soikin
1
@FyodorSoikin:是的,你说得对。犯了一个错误 :( - Willem Van Onsem

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