我在下面的练习中遇到了麻烦:
利用列表推导式,定义一个签名如下的函数:
reproduce :: [Int] -> [Int]
这个函数通过x个自身拷贝来交换列表中的每个数字。
,
input: reproduce[3,5,1]
output: [3,3,3,5,5,5,5,5,1]
我做了以下的事情:
reproduce :: [Int] -> [Int]
reproduce xs = [ x | x <- [1,2..10 ] , x `elem` xs , replicate x x ]
我的思路是让x属于一个小区间,x必须是原始列表的一个元素,所以使用elem
x只会在它属于原始列表时添加,并复制x, x次,以获得x个自己的副本。
当我尝试加载这个函数时,我得到以下错误消息:
Couldn't match expected type `Bool' with actual type `[Int]'
In the return type of a call of `replicate'
In the expression: replicate x x
In a stmt of a list comprehension: replicate x x
我不知道如何修复这个错误,我假设它与elem
部分有关,但我不知道是什么。
注意:这是一个初学者练习,因此应该以一种简单的方式解决。
列表推导式由结果表达式L
和一个或多个逗号分隔的右式R1
, R2
,…组成。如下所示:
[ L | R1, R2, ... ]
右边的每个形式必须是(1)一个生成器:
pattern <- expression
或(2)let
绑定:
let pattern = expression
或(3)一个过滤器条件(一个返回Bool
的表达式):
expression
在你的代码中,我们有三个这样的形式。x <- [1,2..10 ]
是一个生成器(情况2),x `elem` xs
是一个过滤器条件(情况3),但replicate x x
不符合这些条件。这就是错误信息的内容:Haskell期望表达式的类型为Bool
,但replicate
返回的是一个列表。
要真正解决这个问题,您可以这样开始:
notQuiteReproduce xs = [ replicate x x | x <- xs ]
现在notQuiteReproduce [3, 5, 1]
产生[[3,3,3],[5,5,5,5,5],[1]]
。剩下的就是将结果列表"平面化"。这也可以通过列表理解来完成,但我不愿意直接给出解决方案。