dominik
dominik

Reputation: 11

Haskell: Monad return list

I'm trying to write some code in Haskell and there is problem that i can't solve

f 0 = []
f n = do
    x <- [0..4]
    y <- x:(f (n-1))
    return y

The output is:

[0,0,0,1,2,3,4,1,0,1,2,3,4,2,0,1,2,3,4,3,0,1,2,3,4,4,0,1,2,3,4,1,0,0,1,2,3,4,1,0,1,2,3,4,2,0,1,2,3,4,3,0,1,2,3,4,4,0,1,2,3,4,2,0,0,1,2,3,4,1,0,1,2,3,4,2,0,1,2,3,4,3,0,1,2,3,4,4,0,1,2,3,4,3,0,0,1,2,3,4,1,0,1,2,3,4,2,0,1,2,3,4,3,0,1,2,3,4,4,0,1,2,3,4,4,0,0,1,2,3,4,1,0,1,2,3,4,2,0,1,2,3,4,3,0,1,2,3,4,4,0,1,2,3,4]

but I need it to be:

[[0,0,0],[0,0,1],[0,0,2],[0,0,3],[0,0,4],[0,1,0],[0,1,1]...

Any ideas?

Upvotes: 1

Views: 104

Answers (4)

wshcdr
wshcdr

Reputation: 967

cross = do
x <- [0..4]
y <- [0..4]
z <- [0..4]
return [x,y,z]

Upvotes: 0

Jedai
Jedai

Reputation: 1477

So you want the elements of your final list to be lists themselves ?

In the List monad, each <- remove one enclosing from the type, in other words :

(x :: a) <- (xs :: [a])

So it is clear that x :: Int in your code. And you wish for your function to return [[Int]] so what should be the type of x:(f (n-1)) ? You see that this expression shouldn't typecheck if f type was correct so there is your problem : you don't want to cons x to the result of f (n-1) but to each of the results of f (n-1) thus :

f n = do
  x <- [0..4]
  xs <- f (n-1)
  return (x : xs)

If you try this you should see it doesn't work, this is because your f 0 should contain one possibility :

f 0 = return [] -- or [[]]

Upvotes: 3

chi
chi

Reputation: 116174

Others have already answered, but you may wish to know there's already a function like yours in the standard library:

> import Control.Monad
> replicateM 3 [0..4]
[[0,0,0],[0,0,1],[0,0,2],[0,0,3],[0,0,4],[0,1,0],[0,1,1], ...

Upvotes: 4

zw324
zw324

Reputation: 27210

Let's desugar first:

f 0 = []
f n = [0 .. 4] >>= \x -> x : (f (n - 1)) >>= \y -> return y

Note

xs >>= f = concat (map f xs)

[0..4] >>= \x -> x : (f (n - 1)) will simply return [0..4] when n is 1. However, it need to be [[0], [1], [2], [3], [4]],

Thus, the following will do:

f 0 = [[]]
f n = [0 .. 4] >>= \x -> map (x:) (f (n - 1)) >>= \y -> return y

Upvotes: 2

Related Questions