我可以整齐地计算多维数据集列表吗?

fre*_*low 4 haskell list-comprehension

可以使用更高阶函数简化以下函数,Monads或者你有什么用?

cube list = [(x, y, z) | x <- list, y <- list, z <- list]
Run Code Online (Sandbox Code Playgroud)

该函数只是创建列表元素的所有三重排列的列表.例如:

> cube [1..2]
[(1,1,1),(1,1,2),(1,2,1),(1,2,2),(2,1,1),(2,1,2),(2,2,1),(2,2,2)]
Run Code Online (Sandbox Code Playgroud)

Edw*_*ang 10

从比尔的答案来看,因为这是代码使用列表monad,我们可以使用"applicative"样式来做"具有更高阶函数".这是否是一个好主意留给工程师的练习.

import Control.Applicative

cube :: [a] -> [b] -> [c] -> [(a,b,c)]
cube x y z = (,,) <$> x <*> y <*> z
Run Code Online (Sandbox Code Playgroud)

  • 你也可以毫无意义地做到这一点,`cube = liftA3(,,)` (9认同)
  • @FredOverflow:在GHCi中尝试`(,,)<$> getLine <*> getLine <*> getLine`.什么`<*>`它需要两个[motes](http://blog.plover.com/prog/haskell/monad-terminology.html)并将第一个结果应用到第二个.`<$>`是相似的,除了它在左侧而不是微尘上采用纯函数.当应用于列表而不是IO动作时,`(\ xyz - >(x,y,z))<$> list1 <*> list2 <*> list3`与`[(x,y,z)完全相同| x < - list1,y < - list2,z < - list3]`. (3认同)
  • @John:但是,这应该是一个论点.: - ] (2认同)

Joe*_*ams 8

虽然它为您提供了列表而不是元组,但您可以使用Control.Monad中sequence函数:

> let list = [1..2]
> sequence [list, list, list]
[[1,1,1],[1,1,2],[1,2,1],[1,2,2],[2,1,1],[2,1,2],[2,2,1],[2,2,2]]
Run Code Online (Sandbox Code Playgroud)

sequence功能很整洁,因为虽然它的"预期"目的是获取一个动作列表,按顺序执行它们,并将它们的结果返回到列表中,在列表中使用它monad为您提供免费组合.

> sequence $ replicate 3 "01"
["000","001","010","011","100","101","110","111"]
Run Code Online (Sandbox Code Playgroud)


Bil*_*ill 7

实际上,您的列表理解是List monad的用法.

另一种写这个的方法是:

cube :: [a] -> [(a,a,a)]
cube list = do
  x <- list
  y <- list
  z <- list
  return (x, y, z)
Run Code Online (Sandbox Code Playgroud)

  • 我认为值得强调的是,这个答案,原始列表理解和Edward Z.Yang的"Applicative"版本不仅仅是完成*相同的任务*,而且实际上是表达*完全相同的想法的不同方式*. (6认同)

Car*_*arl 6

这不是一个真正的答案,但无论如何我都要提出建议.主要是为了疯狂.

import Control.Monad
import Control.Monad.Instances

cube :: [a] -> [(a, a, a)]
cube = join . join $ liftM3 (,,)
Run Code Online (Sandbox Code Playgroud)

玩得开心.:)