-- let's give ourselves a nice prompt Prelude> :set prompt "ghci> " -- ok, now, what's the type signature for fmap? ghci> :type fmap fmap :: (Functor f) => (a -> b) -> f a -> f b -- Aha! So we see that it takes a function, and a Functor. I think we -- know how to create, or how to recognize a function (a -> b). -- What about Functors, what can we plug there? ghci> :info Functor class Functor f where fmap :: (a -> b) -> f a -> f b (GHC.Base.<$) :: a -> f b -> f a -- Defined in GHC.Base instance Functor Maybe -- Defined in Data.Maybe instance Functor  -- Defined in GHC.Base instance Functor IO -- Defined in GHC.Base -- Interesting. A Functor is not a data type, but a typeclass. -- An interface, for those of us with OO background. -- Furthermore, we see that the following types implement the -- Functor typeclass: Maybe, , and IO. -- So it would seem that fmap allows us to apply a function to a value -- wrapped inside a Functor. Let's find something that we can use -- test this. ghci> :module +Data.Time ghci> :type getCurrentTime getCurrentTime :: IO UTCTime -- So, the getCurrentTime function returns to us a UTCTime wrapped -- in the IO monad. Furthermore, we have seen that IO implements Functor, -- so IO UTCTime could fit the bill for the "f a" that we have a -- need for in fmap. Now we need a function that takes -- a UTCTime and returs something. Hmmm... Let's turn to hoogle -- (at http://www.haskell.org/hoogle/) and search for functions that have -- (UTCTime -> a) type signature. Ah! There is one, let's check it out: ghci> :type utctDay utctDay :: UTCTime -> Day -- This UTCTime -> Day also fits the (a -> b) that we need for fmap! -- So, recapping: -- for fmap :: (Functor f) => (a -> b) -> f a -> f b -- we have: -- utctDay :: UTCTime -> Day for the place of (a -> b) -- getCurrentTime :: IO UTCTime for the place of f a -- ... and according to fmap's type, we should expect IO Day as a result. -- Let's check: ghci> :t fmap utctDay getCurrentTime fmap utctDay getCurrentTime :: IO Day -- Great! All the ends match :) Let's see what this does: ghci> fmap utctDay getCurrentTime 2010-09-09That was pretty easy, wasn't it?
September 9, 2010
Type chasing 'fmap'
I recently tried to explain Haskell's fmap type signature to someone, and discovered that it was a lot easier than the first time I tried to understand (or explain) some of the Linq type signatures. The issue was trying to figure out what "things" can be passed to fmap, and what can be expected back. Here is a sample ghci session that I used to explain just that.