2

这似乎是一个非常常见的操作,但由于某种原因我在 hoogle 中找不到它。无论哪种方式,这都是一个有趣的思考练习。我天真的实现:

pluckL :: [a] -> Int -> Maybe ( a, [a] )
pluckL xs idx = if idx < length xs then Just $ pluck' xs idx else Nothing
where
    pluck' l n = let subl = drop n l in ( head subl, rest l n ++ tail subl )
    rest   l n = reverse $ drop ( length l - n ) $ reverse l

我的主要抱怨是我翻转列表太多次,所以我正在寻找一种创造性的方式,你可以遍历列表一次并生成元组。

4

3 回答 3

7

永远不会有有效的方法。但至少可以有一个漂亮的方法:

pluckL xs i = case splitAt i xs of
    (b, v:e) -> Just (v, b ++ e)
    _ -> Nothing
于 2013-03-10T15:50:52.590 回答
1

reverse如果您使用累加器,您可以在列表中进行越来越少的操作:

pluckL :: [a] -> Int -> Maybe (a, [a])
pluckL xs idx = pluck xs idx [] where
    pluck (x:xs) 0 acc = Just $ ( x, (reverse acc) ++ xs )
    pluck (x:xs) i acc = pluck xs (i-1) (x:acc)
    pluck [] i acc = Nothing
于 2013-03-10T15:48:20.617 回答
1

您可以使用elem检查 elem 是否在列表中,然后根据结果返回 Nothing 或使用delete x从列表中删除 x,例如,

pluckL :: Eq a => [a] -> a -> Maybe (a, [a]) 
pluckL xs0 x =  
    if (x `elem` xs0) 
    then Just (x, xs) 
    else Nothing
        where xs = delete x xs0
于 2013-03-10T15:51:18.770 回答