以下是函数的定义:
fmap :: (a -> b) -> f a -> f b
你们能解释一下它究竟意味着什么吗?我不明白的是f a
和f b
:为什么可以这样写?我的意思是,为什么它的语法正确且编译得很好?
我认为应该只有一个变量(a -> b) -> a -> b
或(a -> b) -> f -> f
或其他(a -> b) -> c -> d
再一次,问题不是关于函数的意义,而是关于语法的正确性。
答案 0 :(得分:7)
您是否接受“普通”map
函数map :: (a -> b) -> [a] -> [b]
的签名?
现在假装我们写了[a]
而不是List a
(与Maybe a
比较),以便签名读取map :: (a -> b) -> List a -> List b
。此签名位于(a -> b) -> f a -> f b
表单f = List
。
函数fmap :: (a -> b) -> f a -> f b
是map
对Maybe
等其他类型构造函数的推广。
答案 1 :(得分:4)
井Haskell [1]类型签名由3个元素组成
现在你的例子我们有2个元素。 a
,b
和f
是类型变量,然后我们有函数箭头。
a
和b
具有*
种类,这意味着它们可以按具体类型实例化。另一方面,f
具有类型* -> *
[2]。这意味着f
无法以与a
和b
相同的方式进行实例化。需要使用类型为*
的类型进行实例化,然后生成具体类型。
例如,在构造该类型的值之前,必须为Maybe
提供另一种类型,例如Int
。例如Just 1 :: Maybe Int
但wat :: Maybe
没有意义。因此,应用f a
与将值函数f
应用于值a
相同,但类型除外。你甚至有部分申请!
因此,请将f a -> f b
视为“将某种类型f
设为某种类型a
的函数,并将其应用于某些类型f
,并返回应用于某些类型b
的值输入->
“。
[1] Haskell我的意思是vanilla haskell。类型运算符,排名N类型等使事情变得复杂。
[2]这是不正常函数{{1}}。它谈论的是类型而不是价值观。
答案 2 :(得分:2)
Haskell中的语法Type1 Type2
意味着类型的应用。例如,您可能已经看到类型Maybe Integer
。它的工作原理是因为Maybe
定义如下:
data Maybe a = ...
请注意类型变量a
。这意味着我们必须将Maybe
应用于某种类型才能将其用作类型本身。在Maybe Integer
中,此a
设置为Integer
。
现在在问题中,我们有f a
,即类型变量应用于另一个类型变量。这意味着f
可能类似Maybe
,可能会应用于另外一种类型,而a
可能类似于Integer
类型。< / p>