0

如果输入是列表,我对列表理解有一些问题。

在所有这些III练习中,不允许使用map:filterconcat!!!


第一部分

要求:

一个函数f1获取一个xs三元组列表,(a, b, cs)其中 类型ab类型Int c是类型[Int]

该函数应该生成一个对的列表(a · b, b + c),因为 cs 中的所有 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)]

第三种方法:

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]

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

再次感谢

第三部分来了……

4

3 回答 3

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

我留下了几个 {-TODO-} 供您填写。


第二部分。

如果你不得不写

g1' :: [[Int]] -> [Int]

你会怎么做?然后你能修改g1'g1你想要的吗?

于 2013-05-14T18:14:16.563 回答
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.

于 2013-05-14T18:15:57.230 回答
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 是如何解决该问题的。两种不同的方法,都很好。

于 2013-05-14T18:22:15.623 回答