如何在haskell中使用map,concat替换3参数列表理解

时间:2011-10-19 10:20:55

标签: haskell

我对列表理解的理解很少。我理解表达式:

[x * x | x <- [1..10]]
should output [1,4,9,16,25,36,49,64,81,100]

并且该表达式的效果与:

相同
map power [1..10]
power x = x * x

现在,我必须找到以下函数的其他方法(就像上面这样):

[(x,y+z) | x <- [1..10], y <- [1..x], z <- [1..y]]

我无法自行解决,请帮助我

3 个答案:

答案 0 :(得分:7)

Haskell Report告诉我们如何翻译列表推导:

[ e | True ]         = [e]
[ e | q ]            = [ e | q, True ]
[ e | b, Q ]         = if b then [ e | Q ] else []
[ e | p <- l, Q ]    = let ok p = [ e | Q ]
                           ok _ = []
                       in concatMap ok l
[ e | let decls, Q ] = let decls in [ e | Q ]

由于你的列表理解只使用无可辩驳的模式(即永不失败的模式),上面的第四个条款有所简化:

[ e | p <- l, Q ]    = concatMap (\p -> [ e | Q ]) l

我将使用此版本进行简洁,但真正的派生应使用报告中的定义。 (家庭作业:尝试真正的翻译,并检查你到底得到了“同样的东西”。)让我们试一下,好吗?

  [(x,y+z) | x <- [1..10], y <- [1..x], z <- [1..y]]
= concatMap (\x -> [(x,y+z) | y <- [1..x], z <- [1..y]] [1..10]
= concatMap (\x -> concatMap (\y -> [(x,y+z) | z <- [1..y]]) [1..x]) [1..10]
= concatMap (\x -> concatMap (\y -> [(x,y+z) | z <- [1..y], True]) [1..x]) [1..10]
= concatMap (\x -> concatMap (\y -> concatMap (\z -> [(x,y+z) | True]) [1..y]) [1..x]) [1..10]
= concatMap (\x -> concatMap (\y -> concatMap (\z -> [(x,y+z)]) [1..y]) [1..x]) [1..10]

我们终于处于一个没有列表推导的版本。

如果你对monad很满意,那么你也可以通过观察concatMap是列表的(>>=)函数的翻转版本来深入了解这个表达式的行为。此外,[e]与列表的return e类似。所以,用monad运算符重写:

= [1..10] >>= \x ->
  [1..x]  >>= \y ->
  [1..y]  >>= \z ->
  return (x,y+z)

答案 1 :(得分:5)

[(x,y+z) | x <- [1..10], y <- [1..x], z <- [1..y]]

相同
concatMap
    (\x -> [(x,y+z) | y <- [1..x], z <- [1..y]])
    [1..10]

您可以类似地从列表推导中提取yz个变量。 (但是你必须按照从左到右的顺序进行操作:接下来是y,最后是z。)

concatMap是Prelude中定义的函数:

concatMap :: (a -> [b]) -> [a] -> [b]
concatMap f = concat . map f

答案 2 :(得分:3)

您可以将其转换为do - 符号:

foo = do x <- [1..10]
         y <- [1..x]
         z <- [1..y]
         return (x, y+z)

这是有效的,因为list是monad。 do - 符号本身只是monadic计算的语法糖。遵循这些令人畏惧的规则(在“去除障碍物”下描述here),你最终会得到:

[1..10] >>= (\x -> [1..x] >>= (\y -> [1..y] >>= (\z -> [(x,y+z)])))

运算符>>=Control.Monad中定义,相当于带有列表翻转参数的concatMap。在列表的情况下,return t只是[t]