2

我正在学习一些 Haskell,并且试图了解模式匹配的工作原理。为此,我编写了一个简单的nth函数。

nth' :: Integer -> [a] -> a
nth' n [] = error "Index out of bound"
nth' n (x:xs) = if n == 0 then x else nth' (n - 1) xs

这第一个实现似乎按预期工作。

-- nth' 25 ['a'..'z']
-- 'z'
-- nth' 26 ['a'..'z']
-- *** Exception: Index out of bound

但是,当我重构它用模式匹配替换 if 语句时,我最终得到了“索引越界”异常,而我显然不应该这样做。

nth' :: Integer -> [a] -> a
nth' _ [] = error "Index out of bound"
nth' 0 (x:[]) = x
nth' n (_:xs) = nth' (n - 1) xs

-- nth' 2 ['a'..'z']
-- *** Exception: Index out of bound

我究竟做错了什么?

4

3 回答 3

13

该模式x:[]匹配一​​个只包含一个元素的列表。因此nth' 0 (x:[]),仅当第一个参数为 0 且第二个参数为单元素列表时,才会执行您的案例。如果第二个参数是一个包含多个参数的列表,它将进入最后一种情况。

您需要将第二种情况更改为nth' 0 (x:_) = x,以便无论列表中有多少元素(只要它至少是一个),它都匹配。

于 2013-03-09T16:25:19.850 回答
6

有问题的条款:

nth' 0 (x:[]) = x

它只匹配一个元素列表。尝试更改它:

nth' 0 (x:_) = x
于 2013-03-09T16:26:03.933 回答
1

尝试:

    nth' :: Integer -> [a] -> a
    nth' _ [] = error "Index out of bound"
    -- nth' 0 (x:[]) = x -- matches one element list x:[] = [x]
    nth' 0 (x:_) = x     -- matches first element and everything (not just empty list)
    nth' n (_:xs) = nth' (n - 1) xs
于 2013-03-09T16:35:30.400 回答