假设我们在参数中有一个列表,并且在其头部和尾部分别匹配模式,所以我们使用x:xs
. 这意味着输入被分成一个值x
和一个列表xs
。
因此,冒号之前的任何内容都被视为单个值,而冒号表示法中的最后一个内容将是列表的其余部分,x
删除了单个值。
但是,如果我想将最后一个值与其余值分开怎么办?似乎不能使用这种表示法。
更新:我想我知道如何使用递归找到最后一个数字,但是你不能简单地通过某种模式匹配得到它,这是真的吗?
假设我们在参数中有一个列表,并且在其头部和尾部分别匹配模式,所以我们使用x:xs
. 这意味着输入被分成一个值x
和一个列表xs
。
因此,冒号之前的任何内容都被视为单个值,而冒号表示法中的最后一个内容将是列表的其余部分,x
删除了单个值。
但是,如果我想将最后一个值与其余值分开怎么办?似乎不能使用这种表示法。
更新:我想我知道如何使用递归找到最后一个数字,但是你不能简单地通过某种模式匹配得到它,这是真的吗?
Haskell 数据类型[a]
将列表表示为单链 cons 列表:模式匹配x:xs
不仅仅是符号,而是它在内存中的存储方式,作为 head 和其余部分的 cons。
正如您在更新中提到的,您可以编写一个函数,该函数遍历一个列表并将其拆分为一个 init 部分和一个最后一个元素:
unsnoc :: [a] -> Maybe ([a], a)
您可以使用视图模式在模式匹配中使用它:
f (unsnoc -> Just (xs, x)) = ...
f [] = ...
您甚至可以将其包装成模式同义词:
pattern xs :> x <- (unsnoc -> Just (xs, x))
(或双向版本
pattern xs :> x <- (unsnoc -> Just (xs, x)) where
xs :> x = xs ++ [x]
)
允许你写
f (xs :> x) = ...
f [] = ...
但是请注意,所有这些方法仍然需要遍历整个列表的主干,因为它们最终都只是调用您的unsnoc
函数。
对于任意列表,您不能,但对于固定大小的列表,您可以模式匹配到最后一个元素(或任何其他任意元素),例如
lastof4 [_,_,_,x] = x
lastof4 [1..4]
4