Jump to content

Haskell list problem

- - - - -

  • Please log in to reply
4 replies to this topic

#1
user034

user034

    Newbie

  • Members
  • Pip
  • 3 posts
Hello, I need to write a Haskell function that has:
input: a list of numbers >0 representing maximum values
output: a list of any possible combination of integers from 0 to the max-values
Here is an example:
If I wrote "function [4,2,3]" it should return the following list:
[ [0,0,0], [0,0,1], [0,0,2], [0,0,3], [0,1,0], [0,1,1], [0,1,2], [0,1,3], [0,2,0], [0,2,1], [0,2,2], [0,2,3], [1,0,0], and so on... [4,2,0], [4,2,1], [4,2,2], [4,2,3] ]

I know how to do this with a defined-length (pseudo)list this way:

functionL :: (Int,Int,Int) -> [(Int, Int, Int)]
functionL (a,b,c) = [ (a',b',c') | a'<-[0..a], b'<-[0..b], c'<-[0..c] ]

and it works, but I need a undefined-length list as input. I tried to write something like this:

functionL' :: [Int] -> [[Int]]
functionL' [] = []
functionL' (h:t) = [ (h' : (functionL' t)) | h'<-[0..h]]

but it shows a type error. Is there another way to achieve this?

Any help will be appreciated.

#2
ZekeDragon

ZekeDragon

    Writes binary right handed and hex left handed

  • Moderators
  • 2,103 posts
Uh oh, you're problem is how you're pattern matching against the elements in the list:
functionL' (h:t) = [ (h' : (functionL' t)) | h'<-[0..h]]
Remember how Haskell separates lists, when you perform this (h:t) pattern match, it assigns the first element to h, then the rest of the elements to t, so this is your types:
h :: Int

t :: [Int]
The easiest way to do this (and probably the most Haskell-esque) is to use map (the foldl1 is just used to put it all together from recursion):
functionL (x:xs) = let restList = functionL xs

       in foldl1 (++) $ map (\v -> map (\lst -> v : lst) restList) [0..x]
That's untested, but it should put you on the right track.
Wow I changed my sig!

#3
user034

user034

    Newbie

  • Members
  • Pip
  • 3 posts
You made a little mistake on the 2nd line :) :
functionL []     = []

functionL [x]    = [[0..x]]

functionL (x:xs) = let restList = functionL xs

       in foldl1 (++) $ map (\v -> map (\lst -> v : lst) restList) [0..x]

but it works nice, it's really what I needed, thank you! My Haskell skill is not so good as yours so I still have to understand the third line. Bye.

#4
ZekeDragon

ZekeDragon

    Writes binary right handed and hex left handed

  • Moderators
  • 2,103 posts
Oh no sir, that will not work. This is my output for that function from ghci:
*Prog> functionL [4,2,3]

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

You want this instead:
functionL [x]    = [[y] | y <- [0..x]]
That will work much better.
*Prog> functionL [4,2,3]

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


Wow I changed my sig!

#5
user034

user034

    Newbie

  • Members
  • Pip
  • 3 posts
Ah yes sorry, I didn't post the correct version I was using, I used:
functionL :: [Int] -> [[Int]]

functionL [] = [[]]

functionL (x:xs) = let restList = functionL xs

       in foldl1 (++) $ map (\v -> map (\lst -> v : lst) restList) [0..x]

This will also work correctly. Many thanks for the function!




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users