在haskell函数中映射和过滤

时间:2015-11-08 18:18:44

标签: haskell

我想定义函数doubleOdds :: [Int] - > [Int]将列表中的每个奇数加倍。

我试图像这样写

doubleOdds xs = map (2 *) . filter (funct xs)
        where funct x = x `mod` 2 == 0

但它不起作用。另外我怎么能把它写成过滤器中的一个废除?

doubleOdds xs = map (2 * ) . filter (`mod` 2 == 0??)

1 个答案:

答案 0 :(得分:2)

首先,我会建议您首先编写类型签名,因为这会使编译器 - 抱怨通常更容易理解(因此您的错误更容易看到)

如何突破导致问题的部分并在之后使用map

doubleIfOdd :: Int -> Int
doubleIfOdd n
  | n `mod` 2 == 0 = n
  | otherwise     = 2*n

doubleOdds :: [Int] -> [Int]
doubleOdds = map doubleIfOdd

这应该有效,并且是可读的IMO

这是一个例子:

λ> doubleOdds [1..10]
[2,2,6,4,10,6,14,8,18,10]

所以它将输入列表中每个奇数的数字加倍 - 我想这就是你想要的

对于你问题的另一部分:如果你只是使用过滤器,你不能改变列表的元素 - 你只能使列表更小(你可以得到它的子列表)

因为我被问到谓词是偶数可以写成免费的(== 0) . (`mod` 2)

(首先取余数 mod 2 ,然后检查它是否等于0 - 记住:你必须从右到左阅读这个因为组成如何在math / Haskell中定义

isEven :: Int -> Bool
isEven = (== 0) . (`mod` 2)

doubleOdds = map (2 * ) . filter ((== 0) . (`mod` 2))

但这可读吗? ......我认为不是这样可能会有所改善:

doubleOdds = map (2 * ) . filter (\n -> n `mod` 2 == 0)

还要注意,在这种情况下,xs不应该在左侧,因为这会添加一个额外的(未使用的)参数,你会得到这样的签名:

doubleOdds :: Integral a => t -> [a] -> [a]

代替想要的[Int] -> [Int](请注意t

当然isEven已经存在于前奏中 - 它的名称为even所以你可以做到

doubleOdds = map (2*) . filter even

或者如果你想要xs

doubleOdds = map (2*) $ filter even xs

等。 (有很多的方法来写这个)

请注意,您问题的解释将为您提供

λ> doubleOdds' [1..10]
[4,8,12,16,20]