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

0 haskell list-comprehension translate higher-order-functions map-function

我对列表理解有一点认识.我理解的表达方式:

[x * x | x <- [1..10]]
should output [1,4,9,16,25,36,49,64,81,100]
Run Code Online (Sandbox Code Playgroud)

并且该表达式的效果与以下内容相同:

map power [1..10]
power x = x * x
Run Code Online (Sandbox Code Playgroud)

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

[(x,y+z) | x <- [1..10], y <- [1..x], z <- [1..y]]
Run Code Online (Sandbox Code Playgroud)

我无法自己弄清楚没有错误,请帮助我

Dan*_*ner 8

Haskell的报告告诉我们该怎么翻译列表理解:

[ 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 ]
Run Code Online (Sandbox Code Playgroud)

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

[ e | p <- l, Q ]    = concatMap (\p -> [ e | Q ]) l
Run Code Online (Sandbox Code Playgroud)

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

  [(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]
Run Code Online (Sandbox Code Playgroud)

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

如果你对monad感到满意,那么你也可以通过观察这个concatMap列表(>>=)函数的翻转版本来深入了解这个表达式的行为.而且,[e]就像列表一样return e.所以,用monad运算符重写:

= [1..10] >>= \x ->
  [1..x]  >>= \y ->
  [1..y]  >>= \z ->
  return (x,y+z)
Run Code Online (Sandbox Code Playgroud)


dav*_*420 5

[(x,y+z) | x <- [1..10], y <- [1..x], z <- [1..y]]
Run Code Online (Sandbox Code Playgroud)

是相同的

concatMap
    (\x -> [(x,y+z) | y <- [1..x], z <- [1..y]])
    [1..10]
Run Code Online (Sandbox Code Playgroud)

您可以类似地从列表推导中提取yz变量.(但你必须按照从左到右的顺序进行:所以y下一个和z最后一个.)

concatMap 是前奏中定义的函数:

concatMap :: (a -> [b]) -> [a] -> [b]
concatMap f = concat . map f
Run Code Online (Sandbox Code Playgroud)