如何在列表中将偶数加倍?

时间:2018-05-26 09:38:11

标签: list haskell

tripleEven :: [Int] -> [Int]
tripleEven list = case list of
    []     -> []
    [x:xs]
        | (x `mod` 2) == 0 = triple x tripleEven xs
        | otherwise        = tripleEven xs
            where triple = (3*)

我一直收到以下错误:

    parse error on input `='
    Perhaps you need a 'let' in a 'do' block?
    e.g. 'let x = 5' instead of 'x = 5'
   |
71 |         | (x `mod` 2) == 0 = triple x tripleEven xs

我希望它通过一个列表,如果数字甚至是三倍。如果是奇数,那么移动到下一个数字直到结束。我是Haskell的新手,只学习语法。如果有人能解释这里到底出了什么问题,那将会很高兴。谢谢。

3 个答案:

答案 0 :(得分:3)

这里有一些问题:

  1. 您使用[x:xs]作为非空列表模式。但是列表有两个数据构造函数[](x:xs)(注意圆括号,实际上括号实际上不是构造函数的一部分,它只是冒号运算符(:));
  2. 在右侧,您需要构建一个新列表。使用triple x tripleEven xs,您不构造新列表:首先计算triple x,然后Haskell旨在执行函数调用,并将该值作为函数。
  3. 您还省略了奇数值:如果值为odd,则在列表上执行递归,因此您不会将这些值放入结果中。
  4. 我们可以将问题解决到:

    tripleEven :: [Int] -> [Int]
    tripleEven [] = []
    tripleEven (x:xs) | even x = (3*x) : tripleEven xs
                      | otherwise = x : tripleEven xs

    但是在这里你基本上执行映射:你可以将函数调用到列表的每个元素,所以我们可以构造一个特殊的映射函数:

    tripleEven :: [Int] -> [Int]
    tripleEven = map f
        where f x | even x = 3 * x
                  | otherwise = x

答案 1 :(得分:3)

这是一个编写函数的递归方法,我只修复了我在代码中注意到的错误。

tripleEven :: [Int] -> [Int]
tripleEven [] -> []
tripleEven (x: xs) = case mod x 2 of
  0 -> (3*x) : tripleEven xs
  _ -> tripleEven xs

tripleEven [1,2,3,4]
# outputs
[6, 12]

TripleEven也可以被视为map& filter操作或列表理解

tripleEven xs = map (*3) $ filter even xs
tripleEven xs = [x*3 | x <- xs, even x]

最后,如果要在where子句中定义triple

tripleEven :: [Int] -> [Int]
tripleEven [] = []
tripleEven (x: xs) = case mod x 2 of
  0 -> trip x : tripleEven xs
         where trip = (*3)    
  _ -> tripleEven xs

答案 2 :(得分:0)

列表类型是一个仿函数,也是一个monad。所以我相信做这项工作的正确方法就是在列表上使用fmap :: Functor f => (a -> b) -> f a -> f b。但是,仅对于列表类型,我们已经拥有与map :: (a -> b) -> [a] -> [b]完全相同的fmap函数。

因此;

Prelude> let trev = map (\n -> if even n then n*3 else n)
Prelude> trev [1,2,3,4]
[1,6,3,12]

应该完美地完成这项工作并且它已被提及。

我们也可以从monadic的角度处理这个任务。然后我们需要一个monadic函数来运行我们的列表元素。是什么让我们的lambda函数monadic在这里是return指令。

Prelude> let trev ns = ns >>= \n -> if even n then return (n*3) else return n
Prelude> trev [1,2,3,4]
[1,6,3,12]