我正在通过Learn You A Haskell来学习 Haskell的基础知识。我对函数式编程和模式匹配都非常满意,但后者更喜欢Mathematica是如何做到的。
head
本着与第 4.1 章中的幼稚实现相同的精神,我继续进行last
如下的幼稚实现:
last1 :: [a] -> a
last1 (_:x:[]) = x
但是,调用last1 [1,2,3,4]
给出了错误Exception: ... Non-exhaustive patterns in function last1
。我知道这个错误意味着指定的模式不涵盖所有可能的输入,通常需要一个包罗万象的模式(我没有提供)。但是,我不确定为什么我的输入会出现此错误。
问题 1:我的理解(我的错误方法)是第一个元素被捕获,_
其余的被分配给x
,这不是我想要的。但是,这不应该给出类型错误吗,因为我指定了[a] -> a
, but x
now is a list?
请注意,这不是关于如何编写一个工作last
函数——我知道我可以把它写成(以及其他可能性)
last2 :: [a] -> a
last2 [x] = x
last2 (_:x) = last2 x
问题 2:在更好地理解 Haskell 中的模式匹配的同一主题下,我如何使用模式匹配来挑选最后一个元素或更一般地,n
从给定列表中挑选出第 th 个元素,比如说,[1..10]
?
这个答案表明您可以使用与ViewPatterns
扩展名匹配的模式来绑定最后一个元素,但似乎很奇怪没有类似的“简单”模式head
在Mathematica中,我可能会将其写为:
Range[10] /. {Repeated[_, {5}], x_, ___} :> x
(* 6 *)
挑选出第 6 个元素和
Range[10] /. {___, x_} :> x
(* 10 *)
挑选出非空列表的最后一个元素。
如果本文稍后会涉及到这一点,我深表歉意,但我试图将遇到的每个主题和概念与我知道的其他语言的处理方式联系起来,以便我能够理解差异和相似之处。