user1670032
user1670032

Reputation: 770

Haskell: Map function onto a list of lists

How do you map a function to operate on lists within a list? The following is just what I'm trying to do as an example, but I was just asking as a general question. Thanks in advance!

Right now, I'm trying to map a function, change, onto each lists of one list (returned by itrCol xs).

evalChange xs = map change $ itrCol xs

where itrCol returns a list of lists, where each containing list is a column.

itrCol xs = [getCol x xs | x <- (take (width xs) (iterate (\x -> (x + 1)*1) 0))]

getCol lists column given list of column indices

getCol :: Int -> [t] -> [t]

and change is:

change []     = []
change [x]    = [x]
change [x,y]  = [x,y]
change (x:y:z:ws) | x == y && y == z = 0 : y*(-1) : 0 : change ws
change (x:xs) =  x : change xs

Upvotes: 10

Views: 11617

Answers (4)

Dan Burton
Dan Burton

Reputation: 53715

The type signature of map is:

map :: (a -> b) -> [a] -> [b]

One sensible type signature for change is:

change :: [Integer] -> [Integer]

Now map expects a function from a to b as its first argument. If we give it change, a function from [Integer] to [Integer], then a = [Integer] and b = [Integer].

map change :: [[Integer]] -> [[Integer]]

Now if that list comprehension produced from iterCol xs supplies a [[Integer]], then we can apply that to map change:

map change (itrCol xs) :: [[Integer]]

This all looks fine to me. It works because map is polymorphic. If you give it a function that turns A into B, then it will give you back a function that turns lists of A into lists of B. It doesn't matter what A and B are: as you can see here, they can even be lists themselves!

Upvotes: 1

Johanna Larsson
Johanna Larsson

Reputation: 10761

Could just use currying and another call to map.

map (map change) $ itrCol xs

To learn more about currying take a look at that chapter in Learn You A Haskell, a great beginner book in Haskell.

Upvotes: 7

luqui
luqui

Reputation: 60543

Check this out!

map           :: (a -> b) ->   [a]   ->   [b]
(map.map)     :: (a -> b) ->  [[a]]  ->  [[b]]
(map.map.map) :: (a -> b) -> [[[a]]] -> [[[b]]]

etc.

Upvotes: 16

Pubby
Pubby

Reputation: 53097

map (and fmap more importantly) essentially lifts a function to work on lists, giving you a new function: (I added superfluous parens to make it more clear)

map :: (a -> b) -> ([a] -> [b])

If you map that second function ([a] -> [b]) you will get a function that works on lists of lists:

evalChange xs = map (map change) $ itrCol xs

(if this is not what you wanted then please clarify)

Upvotes: 3

Related Questions