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)
我无法自己弄清楚没有错误,请帮助我
在Haskell的报告告诉我们该怎么翻译列表理解:
Run Code Online (Sandbox Code Playgroud)[ 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
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)
[(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)
您可以类似地从列表推导中提取y和z变量.(但你必须按照从左到右的顺序进行:所以y下一个和z最后一个.)
concatMap 是前奏中定义的函数:
concatMap :: (a -> [b]) -> [a] -> [b]
concatMap f = concat . map f
Run Code Online (Sandbox Code Playgroud)