Reputation: 770
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
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
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
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
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