SilentDev
SilentDev

Reputation: 22747

Understanding type definitions

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

Answers (2)

sepp2k
sepp2k

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

Robin Zigmond
Robin Zigmond

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

Related Questions