如何修改以下功能,使列表短于搜索索引的情况将导致错误。
elementAt::Int -> [Int] -> Int
elementAt = Data.Foldable.foldl (\x y -> if x == 0 then y else x-1)
1是第一个元素的索引
答案 0 :(得分:6)
使用折叠来查找列表中的第n个元素是一种非常困难的方法。我想使用显式递归向您展示一种更简单的方法:
你必须以不同的方式看待这个问题:
方法的类型签名是:
elementAt :: Int -> [Int] -> Int
只关注第一点,我们知道如果索引是0
,我们想要返回该元素:
elementAt 1 (x:_) = x
现在如果我们的数字大于1
怎么办?在这种情况下,我们希望减少索引结束测试下一项的谓词:
elementAt n (x:xs) = elementAt (n-1) xs
现在我们差不多完成了!如果我们想要在找不到指定位置的元素时抛出错误,我们只需使用error
:
elementAt _ _ = error "Element not found!"
但这不是惯用的Haskell方式的工作方式。一种可能的解决方案是使用Maybe
来包装结果。为此,我们必须稍微更改类型签名:
elementAt :: Int -> [Int] -> Maybe Int
现在该函数能够返回Just
指定位置的元素(如果存在),否则Nothing
:
elementAt 1 (x:_) = Just x
elementAt n (x:xs) = elementAt (n-1) xs
elementAt _ _ = Nothing
为了完整起见,这里有一种可能的方法来实现这个目的:
elementAt n = foldl (\acc x -> if fst x == n then snd x else acc) n . zip [1..n]