Reputation: 515
Lets say
flip :: (a->b->c) ->b->a->c
const ::d->e->d
type of (flip const) would be
a=d,b=e,c=d
in
b->a->c
so the type would be
e->d->d
But for (map take) its
[Int]->[[a]]->[[a]]
so i didn't understand how the ghci this one calculated. i understood the [[a]]->[[a]] but why and how [Int] ?
edit: For example if we'd write in ghci
:t flip const
it would return b->c->c
and ghci would calculate that as i did.
But
map :: (a->b)->[a]->[b]
take :: Int->[c]->[c]
so why is map take
[Int]->[[a]->[a]]
why [Int] how did the ghci calculate that
Upvotes: 7
Views: 509
Reputation: 64740
You should copy and paste the types you see, not re-type them into the question. The reason is you saw wrong. The type for map take
is:
map take :: [Int] -> [[a] -> [a]]
In other words, the unification works as such:
:t map
map :: (a -> b) -> [a] -> [b]
:t take
take :: Int -> [c] -> [c]
so when applying take
as the first argument to map
you get a ~ Int
and b ~ [c] -> [c]
(notice that is a function). Performing these replacements in the map
type and applying the first argument:
map take :: [a] -> [b] (for some specific 'a' and 'b')
-- recall a ~ Int
map take :: [Int] -> [b] (for some specific 'b')
-- recall b ~ [c] -> [c]
map take :: [Int] -> [[c] -> [c]]
Yay, map take
is exactly what you expect. A function that operates over lists of Ints and results in a list of functions that will take some number of elements from the start of a list.
Upvotes: 12
Reputation: 32455
Let's do the same analysis:
map :: (a -> b) -> [a] -> [b]
And
take :: Int -> [x] -> [x]
But that actually means
take :: Int -> ([x] -> [x])
So with a=Int
and b=([x] -> [x])
you get
map take :: [Int] -> [ [x] -> [x] ]
A list of list functions!
Upvotes: 15