6

我试图了解 Haskell 函数定义。我采用了 foldl 函数,它的定义是

:t foldl
foldl :: (a -> b -> a) -> a -> [b] -> a

现在第一个参数是一个函数,所以如果我传递它,剩下的就是:

:t foldl (+)
foldl (+) :: Num b => b -> [b] -> b

我将其读作“一个接受数值并返回接受数组的函数的函数”。

现在,第一个参数真的是一个函数吗?可以读作

foldl :: a -> b -> a -> a -> [b] -> a

反而?

我尝试只传递一个数值,这就是我得到的:

foldl 4 :: Num (a -> b -> a) => a -> [b] -> a

问题是..你怎么读这个?我不明白我有什么。

4

2 回答 2

8

第一个参数是一个函数,因此它不能被读作:foldl :: a -> b -> a -> a -> [b] -> a。因为->是右联想,这意味着a -> b -> ca -> (b -> c)和那是不同的(a -> b) -> c

于 2013-10-07T09:43:59.750 回答
1

'Num' 混在一起是因为你传递(+)foldl. 所以你创建了一个带有签名的函数

foldl (+) :: Num b => b -> [b] -> b

这是一个函数,它接受一个数字和一个数字列表并返回一个数字。

Num b => b 

并不意味着“返回数字的函数 - 这就是它在Scala中的含义。 Num b意味着b此签名其余部分中的所有实例都是数字的。这就是在 Haskell 中完成类型注释的方式。

foldl :: (a -> b -> a) -> a -> [b] -> a

表示一个函数,它接受 3 个参数(其中一个是 function )并返回与第二个参数相同类型的值。遍历签名...

  1. 第一个参数是一个函数,它本身接受两个参数并返回与第一个参数相同类型的值。它在括号中表明它只是一个参数和一个函数 - 括号内的东西是它的函数签名。我们称这个函数为 func
  2. 第二个参数可以是任何东西,只要它与func采用的第一个参数类型相同。
  3. 第三个参数必须是与func采用的第二个参数类型相同的序列
  4. 结果必须与第二个参数(以及func采用的第一个参数)具有相同的类型。

这些是foldl 对这些论点的唯一期望。我们在签名中看到aand因为我们可以有不同的类型作为func的第一个和第二个参数,但是 a 和 b 可以是任何类型,包括两者都是相同的类型。但是,当您将一个函数传递给 foldl,创建一个将func应用于其余参数的新函数时,您添加了任何func的类型期望。由于您传入了一个数字函数,因此该类型注释将添加到生成的签名中。并且由于期望两个参数都是数字,我们在签名中只看到一个类型变量(只是,不是和b+bab)。

于 2013-10-07T10:19:27.127 回答