Online Book Reader

Home Category

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

By Root 442 0
data keyword. Let’s see how the Bool type is defined in the standard library.

data Bool = False | True

Using the data keyword like this means that a new data type is being defined. The part before the equal sign denotes the type, which in this case is Bool. The parts after the equal sign are value constructors. They specify the different values that this type can have. The | is read as or. So we can read this as saying that the Bool type can have a value of True or False. Note that both the type name and the value constructors must start with an uppercase letter.

In a similar fashion, we can think of the Int type as being defined like this:

data Int = -2147483648 | -2147483647 | ... | -1 | 0 | 1 | 2 | ... | 2147483647

The first and last value constructors are the minimum and maximum possible values of Int. It’s not actually defined like this—you can see I’ve omitted a bunch of numbers—but this is useful for illustrative purposes.

Now let’s think about how we would represent a shape in Haskell. One way would be to use tuples. A circle could be denoted as (43.1, 55.0, 10.4), where the first and second fields are the coordinates of the circle’s center and the third field is the radius. The problem is that those could also represent a 3D vector or anything else that could be identified by three numbers. A better solution would be to make our own type to represent a shape.

Shaping Up

Let’s say that a shape can be a circle or a rectangle. Here’s one possible definition:

data Shape = Circle Float Float Float | Rectangle Float Float Float Float

What does it mean? Think of it like this: The Circle value constructor has three fields, which take floats. So when we write a value constructor, we can optionally add some types after it, and those types define the types of values it will contain. Here, the first two fields are the coordinates of its center, and the third one is its radius. The Rectangle value constructor has four fields that accept floats. The first two act as the coordinates to its upper-left corner, and the second two act as coordinates to its lower-right corner.

Value constructors are actually functions that ultimately return a value of a data type. Let’s take a look at the type signatures for these two value constructors.

ghci> :t Circle

Circle :: Float -> Float -> Float -> Shape

ghci> :t Rectangle

Rectangle :: Float -> Float -> Float -> Float -> Shape

So value constructors are functions like everything else. Who would have thought? The fields that are in the data type act as parameters to its value constructors.

Now let’s make a function that takes a Shape and returns its area.

area :: Shape -> Float

area (Circle _ _ r) = pi * r ^ 2

area (Rectangle x1 y1 x2 y2) = (abs $ x2 - x1) * (abs $ y2 - y1)

First, note the type declaration. It says that the function takes a Shape and returns a Float. We couldn’t write a type declaration of Circle -> Float, because Circle is not a type, while Shape is (just as we can’t write a function with a type declaration of True -> Int, for example).

Next, notice that we can pattern match against constructors. We’ve already done this against values like [], False, and 5, but those values didn’t have any fields. In this case, we just write a constructor and then bind its fields to names. Because we’re interested in only the radius, we don’t actually care about the first two fields, which tell us where the circle is.

ghci> area $ Circle 10 20 10

314.15927

ghci> area $ Rectangle 0 0 100 100

10000.0

Yay, it works! But if we try to just print out Circle 10 20 5 from the prompt, we’ll get an error. That’s because Haskell doesn’t know how to display our data type as a string (yet). Remember that when we try to print a value out from the prompt, Haskell first applies the show function to it to get the string representation of our value, and then it prints that to the terminal.

To make our Shape type part of the Show type class, we modify it like this:

data Shape = Circle Float Float Float | Rectangle Float Float Float Float

deriving (Show)

We won’t concern ourselves

Return Main Page Previous Page Next Page

®Online Book Reader