[英]Haskell - a very simple function
我正在尝试理解以下功能:
q1 :: [Int] -> Int
q1 [] = 0
q1 [x] = x
q1 (x:_:xs) = max x (q1 xs)
当输入这个:q1(地图abs [-1,-6,-5,7])时,它得到了我5.有人可以告诉我为什么会这样吗? 我理解map函数如何,但模式匹配(x:_xs)有点令人困惑。 谢谢!
Haskell中的列表 - 至少在概念上 - 是一个链表 。 有两种可能性:
[]
; 要么 (x:xs)
,其中x
是头部 (第一项), xs
是尾部 (列表的其余部分)。 Haskell也使用了语法糖 。 例如[1]
在幕后翻译成(1:[])
, [1,4,2,5]
到(1:(4:(2:(5:[]))))
。
为什么这很重要? 我们首先会尝试了解q1
函数。 如果我们查看类型,我们会看到q1
将Int
s列表作为输入,并返回Int
。 它以递归方式定义为:
q1 :: [Int] -> Int
q1 [] = 0
q1 [x] = x
q1 (x:_:xs) = max x (q1 xs)
这意味着空列表的q1
为零( 0
); 具有一个元素x
的列表的q1
是x
。 对于具有两个或更多元素的列表,该列表x
的第一项的maximum
和该列表尾部的尾部 。 这是因为我们模式匹配(x:_:xs)
,它是(x:(_:xs))
缩写。 下划线基本上意味着“ 不在乎 ”。 因此,名单应该是一个缺点 ,其中尾部是一个缺点 ,以及,我们感兴趣的是列表的头部x
和表尾的尾xs
。
如果我们对此进行推理,我们就会发现q1
返回奇数索引处元素的最大值 (所以第一个,第三个,第五个等元素)。 如果列表具有偶数长度,我们还计算最大值为零(因此,如果奇数索引处的所有元素都是负数,则函数将返回零,但这仅在我们具有偶数长度列表的情况下)。
现在,如果WEL与称之为q1 (map abs [-1,-6,-5,7])
它因而意味着我们将称之为q1
上的结果 map abs
上[-1, -6, -5, 7]
。 map abs
构造一个列表,其中abs
应用于列表的所有元素(尽管它是懒惰地应用)。 所以在map abs [-1, -6, -5, 7]
,我们得到了列表[1, 6, 5, 7]
。 现在奇数索引处的元素是1
和5
。 所以q1
将计算这些元素的最大值和零(因为列表的长度是4,这是偶数)。 并且max(0,1,5)是5 。
就个人而言,尤其是我们也认为零,但仅在列表具有均匀长度的情况下,这是非常“ 不稳定 ”的事实。 它可能导致难以理解的错误,因为它可能是函数细节的结果。 我们可以例如用零计算最大值,而不管列表的长度如何:
q2 :: (Num a, Ord a) => [a] -> a
q2 [] = 0
q2 [x] = max 0 x
q2 (x:_:xs) = max x (q2 xs)
或者我们可以决定不使用零,而不是在空列表上定义最大值,例如:
q3 :: Ord a => [a] -> a
q3 [x] = x
q3 [x,_] = x
q3 (x:_:xs) = max x (q3 xs)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.