Haskell函数定义语法

Adi*_*Adi 3 haskell functional-programming currying

我正在通过以下方式进行列表连接(例如,使用GHC):

myConcat :: [[a]] -> [a]
myConcat xs = foldr (++) [] xs
myConcat    = foldr (++) []
Run Code Online (Sandbox Code Playgroud)

有人可以向我解释一下上述定义为何以及如何运作,而且这个定义没有:

myConcat xs = foldr (++) []
Run Code Online (Sandbox Code Playgroud)

是故意不允许的最后一行代码(由于构造可能会变得混乱,它是无用的等原因)或者是更深层次的东西,可能与currying有关...

我希望我能对此有所了解,这真让我感到困惑:/

后期编辑:除了下面给出的解释,我已经找到了关于这个问题的一个很好的信息来源,作为Chap的"部分功能应用和currying"部分.4"功能编程"来自"真实世界Haskell"一书.这本书可以在线免费获得.

Lan*_*dei 7

让我们回顾一下不同的版本:

myConcat xs = foldr (++) [] xs
Run Code Online (Sandbox Code Playgroud)

这是通常的方式,提供一个被消耗的参数foldr.类型是[[a]] -> [a],因为我们[[a]]在左侧有一个类型的参数,[a]当输入到右侧时会产生.

myConcat = foldr (++) []
Run Code Online (Sandbox Code Playgroud)

foldr部分应用,所以我们返回一个函数,它可以采用一个额外的参数,一个列表列表.所以我们从右侧回来的已经是我们所需要的,它不是"语法上的",而是表达与第一个版本相同的另一种方式.类型再次出现[[a]] -> [a]:左侧没有任何内容,但在右侧返回该签名的功能.

myConcat xs = foldr (++) []
Run Code Online (Sandbox Code Playgroud)

这里foldr也部分应用了,我们返回一个可以像以前一样接受参数的函数,但是我们的定义有一个额外的参数xs,在右侧没有使用.编译器不"知道" 我们想要应用于右侧的这个参数.类型是t -> [[a]] -> [a].为什么?

假设你有一个方形函数:

sqr :: Int -> Int 
sqr x = x*x
Run Code Online (Sandbox Code Playgroud)

你正在做的事情基本上与提供一个未使用的附加参数相同:

sqr:: Int -> t -> Int 
sqr x y = x*x
Run Code Online (Sandbox Code Playgroud)

该函数仍然"有效",例如sqr 3 "bla"产生9,但类型签名是关闭的,未使用的参数是...... erm,未使用.未使用的参数没有固定类型,因为它实际上可以是"任何东西",这无关紧要.因此它t在签名中获得类型variable().