我想定义函数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??)
答案 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]