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

时间:2011-01-05 17:17:28

标签: haskell list-comprehension

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

cube list = [(x, y, z) | x <- list, y <- list, z <- list]

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

> 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)]

6 个答案:

答案 0 :(得分:10)

从Bill的回答来看,因为这是代码使用列表monad,我们可以使用“applicative”样式来做“具有更高阶函数”。这是否是一个好主意留给了工程师。

import Control.Applicative

cube :: [a] -> [b] -> [c] -> [(a,b,c)]
cube x y z = (,,) <$> x <*> y <*> z

答案 1 :(得分: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]]

sequence函数很简洁,因为虽然它的“预期”目的是获取一个操作列表,按顺序执行它们,然后将它们的结果返回到列表中,在列表中使用它monad会给你组合免费。

> sequence $ replicate 3 "01"
["000","001","010","011","100","101","110","111"]

答案 2 :(得分:7)

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

另一种写这个的方法是:

cube :: [a] -> [(a,a,a)]
cube list = do
  x <- list
  y <- list
  z <- list
  return (x, y, z)

答案 3 :(得分:6)

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

import Control.Monad
import Control.Monad.Instances

cube :: [a] -> [(a, a, a)]
cube = join . join $ liftM3 (,,)

玩得开心。 :)

答案 4 :(得分:3)

以乔伊亚当斯所做的为榜样:

g>replicateM 3 [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]]

对于完整的解决方案(传递一个列表并获得3元组),可以这样做:

g>let cube = map (\(a:b:c:_) -> (a, b, c)) . replicateM 3
cube :: [t] -> [(t, t, t)]
(0.00 secs, 526724 bytes)
g>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)]
it :: [(Integer, Integer, Integer)]

但恕我直言,爱德华Z.杨的解决方案至高无上。

答案 5 :(得分:2)

如果你有位,谁需要monads?

import Data.Bits

cube :: [(Int,Int,Int)]
cube = map tuple [0..7] where
   tuple x = (1 + div (x .&. 4)  4, 1 + div (x .&. 2)  2, 1 + x .&. 1)