2

您将如何take使用列表理解来实现?

到目前为止我的方法:

take2 :: (Num i, Ord i) => i -> [a] -> [a]
take2 n xs = [x | x <- xs, [x..n]]
4

4 回答 4

8

列表推导式不适合该take函数的根本原因是:

take函数在元素之后停止对参数列表的评估。n

但是列表推导总是评估生成器中列表的所有元素。Haskell 中没有中断语句。


您可以在列表推导中使用之前或之后使用一些技巧来截断列表,但这样做没有真正意义。这类似于首先使用 normaltake截断列表,然后使用列表推导来返回结果。

于 2018-03-05T12:30:36.057 回答
7

我们可以zip在这里使用一种方法,并枚举元素和索引,例如:

take2 :: (Num i, Enum i) => i -> [a] -> [a]
take2 n xs = [x | (x, _) <- zip xs [1..n]]

或使用ParallelListComp扩展名:

{-# LANGUAGE ParallelListComp #-}

take2 :: (Num i, Enum i) => i -> [a] -> [a]
take2 n xs = [x | x <- xs | _ <- [1..n]]

但实际上take可能首先不是一个非常适合列表理解的函数。

于 2018-03-05T12:17:58.167 回答
0

没有列表理解

take' :: Int -> [Int] -> [Int]
take' _ [] = []
take' _ [x] = [x]
take' n all@(x : xs)
        | (n > length all) = error "Index too large"
        | (n == length all) = all
        | (n == 0) = []
        | (n < length all) =  x : [] ++ (take' (n-1) xs)
于 2019-09-10T23:34:03.873 回答
0
take' :: Int -> [a] -> [a]
take' n xs = [xs !! i | i <- [0..n-1]]
于 2020-01-31T04:21:24.770 回答