使用takewhile和iterate的惯用haskell
我试图通过在线课程学习Haskell。在其中一个练习中,学生应重新编写函数:使用takewhile和iterate的惯用haskell,haskell,Haskell,我试图通过在线课程学习Haskell。在其中一个练习中,学生应重新编写函数: fun1 :: [Integer] -> Integer fun1 [] = 1 fun1 (x:xs) | even x = (x - 2) * fun1 xs | otherwise = fun1 xs 变成更“地道”的哈斯克尔。我将函数重写为 fun1 :: [Integer] -> Integer fun1 xs = let spl = partition even xs in f
fun1 :: [Integer] -> Integer
fun1 [] = 1
fun1 (x:xs)
| even x = (x - 2) * fun1 xs
| otherwise = fun1 xs
变成更“地道”的哈斯克尔。我将函数重写为
fun1 :: [Integer] -> Integer
fun1 xs =
let spl = partition even xs
in foldl (*) 1 ((map (subtract 2) (fst spl)) ++ snd spl)
这似乎。。。莉西。它几乎把一个字一个字地翻译成了我用clojure写它的方式。在赋值中,它给出了使用序言中的
takeWhile
和iterate
重写函数的提示。虽然我表面上了解这些函数的作用,但我并不清楚如何重写该函数以使用它们。如何使用takeWhile
和iterate
重写此代码?这实际上与takeWhile
没有多大关系。对于给定列表中的每个偶数x
,只需在此计算x-2
的乘积。事实上:
fun1 :: [Integer] -> Integer
fun1 [] = 1 -- the product of an empty list is 1
fun1 (x:xs)
-- if the number is even, we multiply (x-2) with the remaining part
| even x = (x - 2) * fun1 xs
-- if the number is odd, we ignore x and return the fun1 of the tail
| otherwise = fun1 xs
所以我们可以这样写:
fun1 :: Integral i => [i] -> i
fun1 = product . map (subtract 2) . filter even
如果您不能使用产品
,您可以使用-就像您在问题中所做的那样-使用:
fun1 :: Integral i => [i] -> i
fun1 = foldl (*) 1 . map (subtract 2) . filter even
这就是我们所说的无点版本:fun1
的头部或任何lambda表达式中都没有参数。因此,我们不是从价值的角度思考问题,而是更多地从功能的角度思考问题
对于列表[1,3,4]
,这将生成:
Prelude> (foldl (*) 1 . map (subtract 2) . filter even) [1,3,4]
2
使用
takeWhile
和iterate
(至少在我看来)编写此函数没有明显、自然的方法。如果有什么区别的话,这是一个心理体操的练习。还要注意的是,您的第二个函数与第一个函数不同——第一个函数忽略奇数值,而第二个函数则不同。@user2407038是的,我误解了这个练习的性质,因此我使用了分区和连接。