繁体   English   中英

Haskell function 定义语法

[英]Haskell function definition syntax

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

myConcat :: [[a]] -> [a]
myConcat xs = foldr (++) [] xs
myConcat    = foldr (++) []

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

myConcat xs = foldr (++) []

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

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

后期编辑:除了下面给出的解释之外,我发现关于此事的一个很好的信息来源是章节“部分 function 应用程序和柯里化”部分 4 来自“Real World Haskell”一书的“函数式编程” 该书可在线免费获取。

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

myConcat xs = foldr (++) [] xs

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

myConcat = foldr (++) []

这里foldr被部分应用,所以我们返回一个 function ,它可以接受一个额外的参数,一个列表列表。 所以我们从右边得到的已经是我们需要的了,它不是“句法糖”,而是和第一个版本一样的另一种表达方式。 类型再次为[[a]] -> [a] :左侧没有任何内容,但在右侧返回该签名的 function。

myConcat xs = foldr (++) []

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

假设你有一个正方形 function:

sqr :: Int -> Int 
sqr x = x*x

您所做的基本上与提供一个未使用的附加参数相同:

sqr:: Int -> t -> Int 
sqr x y = x*x

function 仍然“有效”,例如sqr 3 "bla"产生 9,但类型签名已关闭,未使用的参数是......呃,未使用。 未使用的参数没有固定类型,因为它实际上可以是“任何东西”,没关系。 所以它在签名中获取类型变量( t )。

好吧,让我们看一下curried function foldr的类型签名:

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

因此foldr采用二进制 function (即a->b->b )、一个b值、一个a值列表,并返回一个b值。

让我们也看看foldr文档以获得更清晰的定义:

foldr,应用于二元运算符、起始值(通常是运算符的右标识)和列表,使用二元运算符从右到左减少列表:

现在,让我们看一下myConcat xs = foldr (++) []的类型签名

> :t myConcat
myConcat :: t -> [[a]] -> [a]

嗯……这不是我们想要的……

问题是您从未为foldr提供[a]类型的值。 所以现在, myConcat需要任何类型的值来满足xs类型[a]的值来完成foldr (++) [] ,例如:

> myConcat 2 [[1,2],[3,4]] 
[1,2,3,4]
> myConcat Nothing [[1,2],[3,4]] 
[1,2,3,4]

这行得通,但第一个论点只是浪费。

但是,如果我们将该xs值传递给foldr (++) [] ,例如:

myConcat xs = foldr (++) [] xs

并检查其类型签名

> :t myConcat
myConcat :: [[a]] -> [a]

啊,好多了。 现在myConcat使用xs来完成foldr function。

另外, myConcat = foldr (++) []也可以,实际上是无点编程的一个例子。 如果我们检查foldr (++) []的类型签名,

> :t foldr (++) []
foldr (++) [] :: [[a]] -> [a]

由于我们已经通过部分应用程序foldr提供了它的前两个 arguments ,我们得到一个 function 返回,它将采用[[a]]值并执行我们想要的操作,所以我们只需将其分配给一个名称,它就像示例一样工作上面,但我们不需要显式传递参数!

> let myConcat = foldr (++) []
> :t myConcat
myConcat :: [[a]] -> [a]
> myConcat [[1,2],[3,4]]
[1,2,3,4]
myConcat xs = foldr (++) []

具有类型t -> [[a]] -> [a]与其他两个[[a]] -> [a]的类型不同。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM