简体   繁体   English

Haskell - 一个非常简单的功能

[英]Haskell - a very simple function

I'm trying to understand the following function: 我正在尝试理解以下功能:

q1 :: [Int]  -> Int
q1 []                    = 0
q1 [x]                   = x
q1 (x:_:xs)              = max x (q1 xs)

When inputting this: q1 (map abs [-1,-6,-5,7]), it gets me 5. Can someone walk me through why this happens? 当输入这个:q1(地图abs [-1,-6,-5,7])时,它得到了我5.有人可以告诉我为什么会这样吗? I understand how map functions, but the pattern matching (x:_xs) is a bit confusing. 我理解map函数如何,但模式匹配(x:_xs)有点令人困惑。 Thanks! 谢谢!

A list in Haskell is - at least conceptually - a linked list . Haskell中的列表 - 至少在概念上 - 是一个链表 there are two possibilities: 有两种可能性:

  • an empty list [] ; 空列表[] ; or 要么
  • a "cons" (x:xs) where x is the head (first item), and xs the tail (the rest of the list). 一个“cons” (x:xs) ,其中x头部 (第一项), xs尾部 (列表的其余部分)。

Haskell also uses syntactical sugar . Haskell也使用了语法糖 For instance [1] is behind the curtains translated to (1:[]) , and [1,4,2,5] to (1:(4:(2:(5:[])))) . 例如[1]在幕后翻译成(1:[])[1,4,2,5](1:(4:(2:(5:[]))))

Why is this important? 为什么这很重要? We first will try to understand the q1 function. 我们首先会尝试了解q1函数。 If we look at the type, we see that q1 takes as input a list of Int s, and returns an Int . 如果我们查看类型,我们会看到q1Int s列表作为输入,并返回Int It is defined recursively as: 它以递归方式定义为:

q1 :: [Int]  -> Int
q1 [] = 0
q1 [x] = x
q1 (x:_:xs) = max x (q1 xs)

This means that q1 for an empty list is zero ( 0 ); 这意味着空列表的q1为零( 0 ); that the q1 for a list with one element x is x . 具有一个元素x的列表的q1x For a list with two or more elements is the maximum of the first item of that list x , and tail of the tail of that list. 对于具有两个或更多元素的列表,该列表x的第一项的maximum和该列表尾部的尾部 This is because we pattern match with (x:_:xs) which is short for (x:(_:xs)) . 这是因为我们模式匹配(x:_:xs) ,它是(x:(_:xs))缩写。 The underscore basically means " don't care ". 下划线基本上意味着“ 不在乎 ”。 So the list should be a cons where the tail is a cons as well, and we are interested in the head of the list x , and the tail of the tail of the list xs . 因此,名单应该是一个缺点 ,其中尾部是一个缺点 ,以及,我们感兴趣的是列表的头部x和表尾的尾xs

If we reason about this, we thus find out that q1 returns the maximum of the elements at odd indices (so the first, third, fifth, etc. element). 如果我们对此进行推理,我们就会发现q1返回奇数索引处元素的最大值 (所以第一个,第三个,第五个等元素)。 In case the list has an even length, we also calculate the maximum with zero (so in case the all elements at odd indices are negative, the function will return zero, but this only in the case we have a list of even length). 如果列表具有偶数长度,我们还计算最大值为零(因此,如果奇数索引处的所有元素都是负数,则函数将返回零,但这在我们具有偶数长度列表的情况下)。

Now if wel call it with q1 (map abs [-1,-6,-5,7]) , it thus means that we will call q1 on the result of map abs on [-1, -6, -5, 7] . 现在,如果WEL与称之为q1 (map abs [-1,-6,-5,7])它因而意味着我们将称之为q1上的结果 map abs[-1, -6, -5, 7] map abs constructs a list where abs is applied to all elements of the list (although it is applied lazily). map abs构造一个列表,其中abs应用于列表的所有元素(尽管它是懒惰地应用)。 So after the map abs [-1, -6, -5, 7] , we obtain the list [1, 6, 5, 7] . 所以在map abs [-1, -6, -5, 7] ,我们得到了列表[1, 6, 5, 7] Now the elements at the odd indices are 1 and 5 . 现在奇数索引处的元素是15 So q1 will calculate the maximum of these elements and zero (since the length of the list is four, which is even). 所以q1将计算这些元素的最大值和零(因为列表的长度是4,这是偶数)。 And max(0, 1, 5) is 5 . 并且max(0,1,5)5

Personally, especially the fact that we also consider zero but only in case the list has an even length, is very " unstable ". 就个人而言,尤其是我们也认为零,但仅在列表具有均匀长度的情况下,这是非常“ 不稳定 ”的事实。 It can result in bugs that are hard to understand, since it can be the result of a detail of the function. 它可能导致难以理解的错误,因为它可能是函数细节的结果。 We can for instance calculate the maximum with zero, regardless of the length of the list: 我们可以例如用零计算最大值,而不管列表的长度如何:

q2 :: (Num a, Ord a) => [a] -> a
q2 [] = 0
q2 [x] = max 0 x
q2 (x:_:xs) = max x (q2 xs)

Or we can decide to not use zero at all, and not define maximum over an empty list, like for instance: 或者我们可以决定不使用零,而不是在空列表上定义最大值,例如:

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.

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