Suppose we have a functor. Let’s call it “My Functor”, because that’s a nice friendly name. I’ll call it
for short.
Now, a functor
is—according to higher sources—something which takes any type
to a type
. Let’s see how we can accomplish that with our functor, using Haskell code:
data MyFunctor a = Construct a
This is quite simply a type constructor for our functor for any type
. For example, we can use it on the Integer type as Construct Integer, which will give us the type MyFunctor Integer.
That’s half the definition of a functor. The other half is that it also converts any function
to a function
. This means for any function, it converts that function to work on stuff “inside” the functor.
In terms of our Haskell code, this means that we have a function that acts on another function to modify it. This function is usually called “fmap” (for “functor map” or something similar). This function has the type:
fmap :: (a -> b) -> (MyFunctor a -> MyFunctor b)
It takes any function
to
. Now we can define the function itself. This is the part which will be the most unique for our functor, and we can define it how we like. For our functor, this isn’t going to be very interesting:
fmap f (MyFunctor a) = MyFunctor (f a)
We unwrap the object
from our MyFunctor, apply the function
, then wrap it back up.
Now there are two laws that
must satisfy in order for this to be a “real” functor. In Haskell these are:
(fmap f) . (fmap g) == fmap (f . g) id . fmap == fmap . id == fmap
These can’t be enforced from “within” Haskell, but you must keep them in mind when writing your functor. If you’d like, you can check that these laws hold for our MyFunctor defined above.
Now we have our entire functor:
data MyFunctor a = Construct a fmap f (MyFunctor a) = MyFunctor (f a)
…and in fact, Haskell has a built-in class for functors:
class Functor f where fmap :: (a -> b) -> (f a -> f b)
We can declare our MyFunctor to be a Functor like this:
instance Functor MyFunctor where fmap f (MyFunctor a) = MyFunctor (f a)
…which still doesn’t seem very interesting.
An interesting functor is
. This is defined as:
data List a = Empty | Cons a (List a) instance Functor List where fmap f (Cons first rest) = Cons (f first) (fmap f rest) fmap f Empty = Empty
…wherein the functor takes a type
to a list of
, and
is the familiar map list function, only expressed in a functor context.
Post a Comment