Reputation: 22747
I'm trying to understand type definitions given to me while learning Haskell.
First, this:
fmap_List :: (a -> b) -> [] a -> [] b
fmap_list f [] = [] --1
fmap_list f (x:xs) = f x : fmap_List f xs --2
For 1
, f []
is (a -> b)
right? And then = []
is [] a
. What's [] b
?
For 2
, f (x:xs)
is (a -> b)
. And = f x
is [] a
and : fmap_List f xs
is [] b
, right?
Now, given Maybe
:
data Maybe a = Nothing | Just a
fmap_Maybe :: (a -> b) -> Maybe a -> Maybe b
fmap_Maybe f Nothing = Nothing --3
fmap_maybe f (Just a) = Just (f a) --4
For 3
, f Nothing
is (a -> b)
. = Nothing
is the -> Maybe a
part. Where is the -> Maybe b
part?
For 4
, f (Just a)
is (a -> b)
, = Just (f a)
is -> Maybe a
. So Again, where is the -> Maybe b
part?
And I got No idea how this works (hoping based on the above clarifications, I can figure it out):
fmap_Either :: (a -> b) -> (Either e) a -> (Either e) b
fmap_Either f (Left e) = Left e
fmap_Either f (Right a) = Right (f a)
Thanks!
Upvotes: 2
Views: 118
Reputation: 370082
If we think a curried function as a function taking multiple arguments, then
fmap_List :: (a -> b) -> [a] -> [b]
means that fmap_List
is a two-argument function where the first argument has type a -> b
, the second argument has type [a]
and the result has type [b]
.
fmap_list f [] = [] --1
Here f
is the name given to the first argument of the function, so f
has type a -> b
and the []
pattern is applied to the second argument (of type [a]
). The result of the function is []
, which has type [b]
in accordance with the declared result type.
fmap_list f (x:xs) = f x : fmap_List f xs --2
Again f
has type a -> b
. x:xs
is a pattern that matches the second argument of type [a]
. Since :
is pattern of the type [a]
with the operand types a
and [a]
, this means that x
will have type a
and xs
will have type [a]
. f x : fmap_List f xs
is an expression of type [b]
.
fmap_Maybe f Nothing = Nothing --3
f
is the a -> b
, Nothing
matches the Maybe a
and the Nothing
on the right of the =
is the result of type Maybe b
.
fmap_maybe f (Just a) = Just (f a) --4
Again f
is the a -> b
. Just a
matches the Maybe a
, giving a
the type a
. Just (f a)
is the result of type Maybe b
(f a
having type b
and Just
turning the b
into a Maybe b
).
Upvotes: 7
Reputation: 18249
First let me rewrite your definition of fmap_List
using the more normal notation, where [] a
is written as [a]
fmap_list :: (a -> b) -> [a] -> [b]
fmap_list f [] = []
fmap_list f (x:xs) = f x : fmap_List f xs
The type signature tells you that the function takes 2 arguments: a function of type a -> b
and a list of type [a]
, and that it returns a list of type [b]
. So that must mean that on that second line, for example:
fmap_list f [] = []
the f
has type a -> b
(although the name is arbitrary, it's usual to use things like f
and g
to refer to functions, so this matches up), and the first []
(to the left of the equals sign) has type [a]
. The []
on the right of the equals sign is the result of the function, so is of type [b]
. It's exactly the same on the subsequent line. Let me try to emphasise how the types of the function definition match up with those of the signature with some spacing:
fmap_list :: (a -> b) -> [a] -> [b]
fmap_list f [] = []
fmap_list f (x:xs) = f x : fmap_List f xs
I hope this makes sense now - and I see no need to go through the other 2 examples in the same detail, as for this purpose they're exactly the same. If you need further clarification, please let me know in the comments.
The major error in your assumptions is here (and similar cases): "f []
is (a -> b)
right?" No, f
is of type a -> b
and f []
isn't actually meaningful here (it would mean the value of the function f
applied to []
, but that only works if a
is a list type, something which there is no reason to infer). What appears in the function definition isn't f []
but fmap_list f []
, which is parsed as (fmap_list f) []
.
Upvotes: 5