Reputation: 34099
I've tried following code snippet on prelude:
*ExerciseMonad Control.Monad> :t fmap ((:) 3) []
and got as result an empty []
.
Then I convert an empty list to monad
structure:
*ExerciseMonad Control.Monad> x = return []
*ExerciseMonad Control.Monad> :t x
x :: Monad m => m [t]
the returned value is wrapped in Monad
structure.
It seems like a magic, that I do not get an empty list:
*ExerciseMonad Control.Monad> fmap ((:) 3) x
[3]
Why did not I get an empty list?
Upvotes: 2
Views: 151
Reputation: 26191
fmap ((:) 3) []
Would actually apply the (:) 3
operator to the "contents" of your list functor. As you have no contents you normally get an empty list in return. If in case you had it like;
fmap ((:) 3) [[],[],[]]
then you would get [[3],[3],[3]]
as the return value.
Now if you chose to feed fmap
with a list value. You may feed it with a list value "wrapped" into List value constructor like;
*Main> fmap ((:) 3) $ return []
[3]
Upvotes: 1
Reputation: 144206
In your first example fmap ((:) 3) []
has type Num a => [[a]]
. fmap f [] == []
.
In contrast the type of fmap ((:) 3) x
is (Monad m, Num a) => m [a]
.GHCi deafults m
to IO
so at the prompt it has type Num a => IO [a]
. The corresponding IO action is evaluated and the result is printed if it is an instance of Show
. a
defaults to Integer
and [Integer]
has a Show
instance so it is displayed.
Upvotes: 2
Reputation: 233347
fmap
works on any Functor
, including []
. Note how GHCi infers the type of your first expression:
Prelude> :t fmap ((:) 3) []
fmap ((:) 3) [] :: Num a => [[a]]
The return type is a nested list, because otherwise the cons operator (:
) doesn't make sense. When you fmap
over an empty list ([]
), however, there's nothing to do, so the result is also the empty list.
On the other hand, the type of your second expression is different:
Prelude> x = return []
Prelude> :t x
x :: Monad m => m [t]
Prelude> :t fmap ((:) 3) x
fmap ((:) 3) x :: (Num a, Monad f) => f [a]
You'll notice that the return value is no longer a nested list, but a Monad
over [a]
. Monad
, however, includes Applicative
, which again includes Functor
, so in this second expression, fmap
is no longer the for the []
instance, but for f
. As Lee points out, in GHCi, the default Monad
is IO
, so the fmap
in fmap ((:) 3) x
maps IO
, not []
.
This means that x
actually becomes IO []
in GHCi, and fmap
in the IO
monad applies the mapping function to the data contained inside of the monad ([]
). This means that you get ((:) 3) []
, which is [3]
:
Prelude> ((:) 3) []
[3]
Upvotes: 8