Haskell - 列表理解 - 获取输入元素

时间:2013-05-14 17:44:13

标签: list haskell list-comprehension let

如果输入是列表,我在列表理解方面遇到了一些问题。

在所有 III 练习中,不允许使用:mapfilterconcat !!!


第一部分

要求:

一个funktion f1获取了一个xs三角形(a, b, cs)列表 ab的类型为Int c的类型为[Int]

该函数应生成一对(a · b, b + c)的列表,对于cs中的所有c,生成列表中的c应该只显示第一个元素大于第二个元素的对 - (a · b) > b + c

示例:

f1  [(10,20,[1,10,100]),  (4,5,[5,15,25])] 

应返回以下列表:

[(200,21),(200,30),(200,120),(20,10)]

我的尝试:

f1 :: Int -> Int -> [Int] -> [(Int, Int)]
f1 a b cs = [(a*b, b+c)| c<-cs, (a*b)>(b+c)]

它工作正常,但不是列表作为输入。

所以我尝试了几种方法,但遗憾的是不是正确的方法: - (

f1 :: [(Int, Int, [Int])] -> [(Int, Int)]

第一种方法:

f1 xs = [((xs !! 0)*(xs !! 1), (xs !! 1)+c)| c<-(xs !! 2), ((xs !! 0)*(xs !! 1))>((xs !! 1)+c)]

第二种方法:

f1 let (a, b, cs) = xs = [(a*b, b+c)| c<-cs, (a*b)>(b+c)]

第3种方法:

f1 (a b cs) = [(a*b, b+c)| c<-cs, (a*b)>(b+c)]

这三个都不起作用!

dave4420解决方案:

f1 :: [(Int, Int, [Int])] -> [(Int, Int)]
f1 xs = [ (a*b, b+c) | (a, b, cs) <- xs, c <- cs, (a*b)>(b+c) ]

第二部分

要求:

函数g1获取相同类型的对的列表,并从中生成简单列表。

示例:

g1 [(1,2),(3,4),(5,6)] returns [1,2,3,4,5,6]

我的尝试:

g1 :: [(Int, Int)] -> [Int]
g1 xs = [a,b | (a,b)<-xs]

我得到了一个编译错误,因为列表推导的输出中的a,b没有正确的语法。

但是我可以退回a或b或者例如A + B:

g1 xs = [a | (a,b)<-xs]

g1 xs = [a+b | (a,b)<-xs]

你能帮我解决这个问题吗?

再次感谢

第三部分即将来临......

3 个答案:

答案 0 :(得分:3)

f1 :: [(Int, Int, [Int])] -> [(Int, Int)]
f1 xs = [ {-TODO-} | (a, b, cs) <- xs, c <- cs, {-TODO-} ]

我已经留下了几个{-TODO-}给你填写。


第二部分。

如果你不得不写

g1' :: [[Int]] -> [Int]
你会怎么做?您可以将g1'修改为您想要的g1吗?

答案 1 :(得分:1)

你已经走近了。使用

f1 :: Int -> Int -> [Int] -> [(Int, Int)]
f1 a b cs = [(a*b, b+c)| c<-cs, (a*b)>(b+c)]

首先需要重写一次以获得三倍(Int, Int, [Int])。这是一个微不足道的变化,

f1_a :: (Int, Int, [Int]) -> [(Int, Int)]
f1_a (a,b,cs) = [(a*b, b+c) | c <- cs, a*b > b+c]

现在,您需要将该函数应用于三元组输入列表的每个元素。如果您可以使用map f1_a xs,那将是map,但由于您不能使用f2 :: [(Int, Int, [Int])] -> [[(Int, Int)]] f2 xs = [f1_a x | x <- xs] ,请将其写为列表理解

concat

但是有一个级别的列表太多,你想要一个平面列表,所以你需要concat列表列表。您也不应该使用concat,因此您需要将其写为列表理解。

现在,concat' xss = [x | xs <- xss, x <- xs] 做了什么?

对于参数中的每个列表,对于该列表中的每个元素,将该元素放在结果中,所以

f2

现在将其应用于{{1}}。

答案 2 :(得分:1)

你有90%的路要走。 请记住,在GHCI中,您在定义之前使用let, 但在常规源代码中,你没有。 所以,让我们看看你到目前为止所拥有的。

λ> let f1 (a,b,cs) = [(a*b, b+c)| c<-cs, (a*b)>(b+c)]

请注意,我在元组中添加了逗号。让我们找出f1的类型。

λ> :t f1
f1 :: (Num t, Ord t) => (t, t, [t]) -> [(t, t)]

目前,您可以忽略(Num t, Ord t) =>部分。 这是一个函数,它接受包含元素的元组,另一个元素 元素和元素列表。 所以我们无法将整个元组列表传递给它, 只有一个元组。

λ> f1 (10,20,[1,10,100])
[(200,21),(200,30),(200,120)]
λ> f1 (4,5,[5,15,25])
[(20,10)]

这是你想要的结果的第一部分。

λ> f1 (4,5,[5,15,25])
[(20,10)]

这是第二部分。 所以现在你需要另一个接受如下输入的函数:

[(10,20,[1,10,100]),  (4,5,[5,15,25])]

即,我们需要一个带有元组列表的函数。 在f1的基础上,我们可以这样写:

λ> let f2 xs = [f1 x | x <- xs]
λ> f2 [(10,20,[1,10,100]),  (4,5,[5,15,25])]
[[(200,21),(200,30),(200,120)],[(20,10)]]

请注意,结果是列表列表,我们只需要一个普通列表。 由于您不允许使用concat,请查看groovy或Daniel Fisher如何解决问题。 两种不同的方法,都很好。