您将如何take
使用列表理解来实现?
到目前为止我的方法:
take2 :: (Num i, Ord i) => i -> [a] -> [a]
take2 n xs = [x | x <- xs, [x..n]]
您将如何take
使用列表理解来实现?
到目前为止我的方法:
take2 :: (Num i, Ord i) => i -> [a] -> [a]
take2 n xs = [x | x <- xs, [x..n]]
列表推导式不适合该take
函数的根本原因是:
该take
函数在元素之后停止对参数列表的评估。n
但是列表推导总是评估生成器中列表的所有元素。Haskell 中没有中断语句。
您可以在列表推导中使用之前或之后使用一些技巧来截断列表,但这样做没有真正意义。这类似于首先使用 normaltake
截断列表,然后使用列表推导来返回结果。
我们可以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
可能首先不是一个非常适合列表理解的函数。
没有列表理解
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)
take' :: Int -> [a] -> [a]
take' n xs = [xs !! i | i <- [0..n-1]]