Reputation: 263118
Can the following function be simplified with higher order functions, Monads or what have you?
cube list = [(x, y, z) | x <- list, y <- list, z <- list]
The function simply creates a list of all triple-permutations of the elements of the list. For example:
> 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)]
Upvotes: 4
Views: 513
Reputation: 969
To model after what Joey Adams did:
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]]
For the full solution(pass it a list and get 3-tuples), something like this can be done:
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)]
But IMHO, Edward Z. Yang's solution reigns supreme.
Upvotes: 3
Reputation: 54584
Who needs monads if you can have bits?
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)
Upvotes: 2
Reputation: 27003
This isn't really a serious answer, but I have to suggest it anyway. Mostly for the sake of craziness.
import Control.Monad
import Control.Monad.Instances
cube :: [a] -> [(a, a, a)]
cube = join . join $ liftM3 (,,)
Have fun with that one. :)
Upvotes: 6
Reputation: 26742
Going from Bill's answer, because this is code uses the list monad, we can use "applicative" style to do "with higher-order functions". Whether or not this is a good idea is left as an exercise for the engineer.
import Control.Applicative
cube :: [a] -> [b] -> [c] -> [(a,b,c)]
cube x y z = (,,) <$> x <*> y <*> z
Upvotes: 10
Reputation: 43380
Although it gives you lists instead of tuples, you can use the sequence
function in Control.Monad:
> 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]]
The sequence
function is neat because, although its "intended" purpose is to take a list of actions, do them in order, and return their results in a list, using it on the list monad gives you combinations for free.
> sequence $ replicate 3 "01"
["000","001","010","011","100","101","110","111"]
Upvotes: 8
Reputation: 45418
In fact, your list comprehension is a usage of the List monad.
Another way to write this is:
cube :: [a] -> [(a,a,a)]
cube list = do
x <- list
y <- list
z <- list
return (x, y, z)
Upvotes: 7