So basically I can see that the type definitions would seem to deliver the same thing. I test it

> (concat . (map (map (*5)))) [[1],[2],[3]]
[5,10,15]
> (map (*5) . concat) [[1],[2],[3]]
[5,10,15]

and can also conclude they give the same answer. So is this an example of referential transparency, i.e., the ability to substitute code and be assured both forms/expressions deliver the same answer?


On Wed, Apr 7, 2021 at 12:07 PM Akhra Gannon <tanuki@gmail.com> wrote:
Check the types!

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

Therefore:

map f :: [a] -> [b]

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

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

And,

concat :: [[a]] -> [a]

Put it all together and you should see how that rewrite works!


On Wed, Apr 7, 2021, 9:47 AM Galaxy Being <borgauf@gmail.com> wrote:
I'm in Bird's Thinking Functionally with Haskell and the topic is natural transformations. He says

filter p . map f = map f . filter (p . f)

and he has a proof, but one step of the proof he goes from

filter p . map f = concat . map (map f) . map (test (p . f))

to 

filter p . map f = map f . concat . map (test (p . f))

which means 

concat . map (map f) => map f . concat

which means

map (map f) = map f

... or I'm getting this step wrong somehow. To begin with, I'm having a hard time comprehending map(map f), Any ideas on how this is possible?

LB




_______________________________________________
Beginners mailing list
Beginners@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
_______________________________________________
Beginners mailing list
Beginners@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners