Online Book Reader

Home Category

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

By Root 452 0
declarations as well. The following type declaration really doesn’t make much sense:

(==) :: Maybe -> Maybe -> Bool

But this does:

(==) :: (Eq m) => Maybe m -> Maybe m -> Bool

This is just something to think about, because == will always have a type of (==) :: (Eq a) => a -> a -> Bool, no matter what instances we make.

Oh, and one more thing: If you want to see what the instances of a type class are, just type :info YourTypeClass in GHCi. For instance, typing :info Num will show which functions the type class defines, and it will give you a list of the types in the type class. :info works for types and type constructors, too. If you do :info Maybe, it will show you all the type classes that Maybe is an instance of. Here’s an example:

ghci> :info Maybe

data Maybe a = Nothing | Just a -- Defined in Data.Maybe

instance (Eq a) => Eq (Maybe a) -- Defined in Data.Maybe

instance Monad Maybe -- Defined in Data.Maybe

instance Functor Maybe -- Defined in Data.Maybe

instance (Ord a) => Ord (Maybe a) -- Defined in Data.Maybe

instance (Read a) => Read (Maybe a) -- Defined in GHC.Read

instance (Show a) => Show (Maybe a) -- Defined in GHC.Show

A Yes-No Type Class

In JavaScript and some other weakly typed languages, you can put almost anything inside an if expression. For example, in JavaScript, you can do something like this:

if (0) alert("YEAH!") else alert("NO!")

Or like this:

if ("") alert ("YEAH!") else alert("NO!")

Or like this:

if (false) alert("YEAH!") else alert("NO!")

All of these will throw an alert of NO!.

However, the following code will give an alert of YEAH!, since JavaScript considers any nonempty string to be a true value:

if ("WHAT") alert ("YEAH!") else alert("NO!")

Even though strictly using Bool for Boolean semantics works better in Haskell, let’s try to implement this JavaScript-like behavior, just for fun! We’ll start out with a class declaration:

class YesNo a where

yesno :: a -> Bool

This is pretty simple. The YesNo type class defines one function. That function takes one value of a type that can be considered to hold some concept of trueness and tells us for sure if it’s true or not. Notice that from the way we use a in the function that a must be a concrete type.

Next up, let’s define some instances. For numbers, we’ll assume that (as in JavaScript) any number that isn’t 0 is true in a Boolean context and 0 is false.

instance YesNo Int where

yesno 0 = False

yesno _ = True

Empty lists (and by extension, strings) are a no-ish value, while nonempty lists are a yes-ish value.

instance YesNo [a] where

yesno [] = False

yesno _ = True

Notice how we just put a type parameter a in there to make the list a concrete type, even though we don’t make any assumptions about the type that’s contained in the list.

Bool itself also holds trueness and falseness, and it’s pretty obvious which is which:

instance YesNo Bool where

yesno = id

But what’s id? It’s just a standard library function that takes a parameter and returns the same thing, which is what we would be writing here anyway.

Let’s make Maybe a an instance, too:

instance YesNo (Maybe a) where

yesno (Just _) = True

yesno Nothing = False

We didn’t need a class constraint, because we made no assumptions about the contents of the Maybe. We just said that it’s true-ish if it’s a Just value and false-ish if it’s a Nothing. We still need to write out (Maybe a) instead of just Maybe. If you think about it, a Maybe -> Bool function can’t exist (because Maybe isn’t a concrete type), whereas a Maybe a -> Bool is fine and dandy. Still, this is really cool, because now any type of the form Maybe something is part of YesNo, and it doesn’t matter what that something is.

Previously, we defined a Tree a type that represented a binary search tree. We can say an empty tree is false-ish, and anything that’s not an empty tree is true-ish:

instance YesNo (Tree a) where

yesno EmptyTree = False

yesno _ = True

Can a traffic light be a yes or no value? Sure. If it’s red, you stop. If it’s green, you go. (If it’s yellow? Eh, I usually run the

Return Main Page Previous Page Next Page

®Online Book Reader