我需要获取列表的第 n 个元素,但不使用!!
运算符。我对haskell非常陌生,所以如果您能更详细地回答而不仅仅是一行代码,我将不胜感激。这就是我目前正在尝试的:
nthel:: Int -> [Int] -> Int
nthel n xs = 0
let xsxs = take n xs
nthel n xs = last xsxs
但我得到:解析错误(可能不正确的缩进)
我需要获取列表的第 n 个元素,但不使用!!
运算符。我对haskell非常陌生,所以如果您能更详细地回答而不仅仅是一行代码,我将不胜感激。这就是我目前正在尝试的:
nthel:: Int -> [Int] -> Int
nthel n xs = 0
let xsxs = take n xs
nthel n xs = last xsxs
但我得到:解析错误(可能不正确的缩进)
这里有很多东西有点不对劲,
nthel :: Int -> [Int] -> Int
在技术上是正确的,我们真的想要
nthel :: Int -> [a] -> a
所以我们可以在任何列表上使用它(可选)
nthel n xs = 0
你刚才说的是“不管你付出什么都nthel
返回0”。这显然是错误的。
let xsxs = ...
这不是合法的haskell。let ... in ...
是表达式,不能用于顶层。
从那里我不确定那应该做什么。
也许这会帮助你走上正确的轨道
nthelem n [] = <???> -- error case, empty list
nthelem 0 xs = head xs
nthelem n xs = <???> -- recursive case
尝试填写<???>
您的最佳猜测,我很乐意从那里提供帮助。
或者,您可以使用 Haskell 的“模式匹配”语法。我在这里解释了如何使用列表来做到这一点。
这将我们的上述更改为
nthelem n [] = <???> -- error case, empty list
nthelem 0 (x:xs) = x --bind x to the first element, xs to the rest of the list
nthelem n (x:xs) = <???> -- recursive case
这样做很方便,因为它不需要使用显式head
和tail
s。
我想你的意思是:
nthel n xs = last xsxs
where xsxs = take n xs
...您可以简化为:
nthel n xs = last (take n xs)
我认为你应该尽可能避免使用last
- 列表是从“前端”使用的,而不是从后面使用。您想要的是摆脱前 n 个元素,然后获取剩余列表的头部(当然,如果其余部分为空,则会出现错误)。您可以直接将其表达为:
nthel n xs = head (drop n xs)
或更短:
nthel n = head . drop n
或者有点疯狂:
nthel = (head .) . drop
如您所知,列表不是自然索引的,但可以使用通用技巧来克服它。
试试 ghci, zip [0..] "hello"
, 什么是zip [0,1,2] "hello"
or zip [0..10] "hello"
?
从这个观察开始,我们现在可以很容易地获得一种方法来索引我们的列表。
此外,它很好地说明了懒惰的使用,为您的学习过程提供了很好的提示。
然后基于此并使用模式匹配,我们可以提供一种有效的算法。
现在对于辅助函数,列表不能为空,然后我们可以天真地进行模式匹配,并且,
附加说明,因为我们的函数可能会失败(空列表......),使用 Maybe 类型包装我们的结果可能是一件好事。
把这一切放在一起,我们就结束了。
nth :: Int -> [a] -> Maybe a
nth n xs
| null xs || n < 0 = Nothing
| otherwise = helper n zs
where
zs = zip [0..] xs
helper n ((i,c):zs)
| i == n = Just c
| null zs = Nothing
| otherwise = helper n zs