Online Book Reader

Home Category

Learn You a Haskell for Great Good! - Miran Lipovaca [65]

By Root 434 0
yellows because I live for adrenaline.)

instance YesNo TrafficLight where

yesno Red = False

yesno _ = True

Now that we have some instances, let’s go play!

ghci> yesno $ length []

False

ghci> yesno "haha"

True

ghci> yesno ""

False

ghci> yesno $ Just 0

True

ghci> yesno True

True

ghci> yesno EmptyTree

False

ghci> yesno []

False

ghci> yesno [0,0,0]

True

ghci> :t yesno

yesno :: (YesNo a) => a -> Bool

It works!

Now let’s make a function that mimics the if statement, but that works with YesNo values.

yesnoIf :: (YesNo y) => y -> a -> a -> a

yesnoIf yesnoVal yesResult noResult =

if yesno yesnoVal

then yesResult

else noResult

This takes a YesNo value and two values of any type. If the yes-no--ish value is more of a yes, it returns the first of the two values; otherwise, it returns the second of them. Let’s try it:

ghci> yesnoIf [] "YEAH!" "NO!"

"NO!"

ghci> yesnoIf [2,3,4] "YEAH!" "NO!"

"YEAH!"

ghci> yesnoIf True "YEAH!" "NO!"

"YEAH!"

ghci> yesnoIf (Just 500) "YEAH!" "NO!"

"YEAH!"

ghci> yesnoIf Nothing "YEAH!" "NO!"

"NO!"

The Functor Type Class

So far, we’ve encountered a lot of the type classes in the standard library. We’ve played with Ord, which is for stuff that can be ordered. We’ve palled around with Eq, which is for things that can be equated. We’ve seen Show, which presents an interface for types whose values can be displayed as strings. Our good friend Read is there whenever we need to convert a string to a value of some type. And now, we’re going to take a look at the Functor type class, which is for things that can be mapped over.

You’re probably thinking about lists now, since mapping over lists is such a dominant idiom in Haskell. And you’re right, the list type is part of the Functor type class.

What better way to get to know the Functor type class than to see how it’s implemented? Let’s take a peek.

class Functor f where

fmap :: (a -> b) -> f a -> f b

We see that it defines one function, fmap, and doesn’t provide any default implementation for that function. The type of fmap is interesting. In the definitions of type classes so far, the type variable that played the role of the type in the type class was a concrete type, like the a in (==) :: (Eq a) => a -> a -> Bool. But now, the f is not a concrete type (a type that a value can hold, like Int, Bool, or Maybe String), but a type constructor that takes one type parameter. (A quick refresher example: Maybe Int is a concrete type, but Maybe is a type constructor that takes one type as the parameter.)

We see that fmap takes a function from one type to another and a functor value applied with one type and returns a functor value applied with another type. If this sounds a bit confusing, don’t worry—all will be revealed soon when we check out a few examples.

Hmm . . . the type declaration for fmap reminds me of something. Let’s look at the type signature of the map function:

map :: (a -> b) -> [a] -> [b]

Ah, interesting! It takes a function from one type to another and a list of one type and returns a list of another type. My friends, I think we have ourselves a functor! In fact, map is just a fmap that works only on lists. Here’s how the list is an instance of the Functor type class:

instance Functor [] where

fmap = map

That’s it! Notice how we didn’t write instance Functor [a] where. This is because f must be a type constructor that takes one type, which we can see in the following type declaration:

fmap :: (a -> b) -> f a -> f b

[a] is already a concrete type (of a list with any type inside it), while [] is a type constructor that takes one type and can produce types such as [Int], [String], or even [[String]].

Since for lists, fmap is just map, we get the same results when using these functions on lists:

ghci> fmap (*2) [1..3]

[2,4,6]

ghci> map (*2) [1..3]

[2,4,6]

What happens when we map or fmap over an empty list? Well, of course, we get an empty list. It turns an empty list of type [a] into an empty list of type [b].

Maybe As a Functor


Types that can act like a box can be functors. You can

Return Main Page Previous Page Next Page

®Online Book Reader