Online Book Reader

Home Category

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

By Root 552 0
and types in a module. We start off like this:

module Shapes

( Point(..)

, Shape(..)

, area

, nudge

, baseCircle

, baseRect

) where

By using Shape(..), we export all the value constructors for Shape. This means that people who import our module can make shapes by using the Rectangle and Circle value constructors. It’s the same as writing Shape (Rectangle, Circle), but shorter.

Also, if we decide to add some value constructors to our type later on, we don’t need to modify the exports. That’s because using .. automatically exports all value constructors for a given type.

Alternatively, we could opt to not export any value constructors for Shape by just writing Shape in the export statement, without the parentheses. That way, people who import our module could make shapes only by using the auxiliary functions baseCircle and baseRect.

Remember that value constructors are just functions that take the fields as parameters and return a value of some type (like Shape). So when we choose not to export them, we prevent the person importing our module from using those value constructors directly. Not exporting the value constructors of our data types makes them more abstract, since we’re hiding their implementation. Also, whoever uses our module can’t pattern match against the value constructors. This is good if we want people who import our module to be able to interact with our type only via the auxiliary functions that we supply in our module. That way, they don’t need to know about the internal details of our module, and we can change those details whenever we want, as long as the functions that we export act the same.

Data.Map uses this approach. You can’t create a map by directly using its value constructor, whatever it may be, because it’s not exported. However, you can make a map by using one of the auxiliary functions like Map.fromList. The people in charge of Data.Map can change the way that maps are internally represented without breaking existing programs.

But for simpler data types, exporting the value constructors is perfectly fine, too.

Record Syntax

Now let’s look at how we can create another kind of data type. Say we’ve been tasked with creating a data type that describes a person. The information that we want to store about that person is first name, last name, age, height, phone number, and favorite ice cream flavor. (I don’t know about you, but that’s all I ever want to know about a person.) Let’s give it a go!

data Person = Person String String Int Float String String deriving (Show)

The first field is the first name, the second is the last name, the third is the age, and so on. Now let’s make a person.

ghci> let guy = Person "Buddy" "Finklestein" 43 184.2 "526-2928" "Chocolate"

ghci> guy

Person "Buddy" "Finklestein" 43 184.2 "526-2928" "Chocolate"

That’s kind of cool, although slightly unreadable.

Now what if we want to create functions to get specific pieces of information about a person? We need a function that gets some person’s first name, a function that gets some person’s last name, and so on. Well, we would need to define them like this:

firstName :: Person -> String

firstName (Person firstname _ _ _ _ _) = firstname

lastName :: Person -> String

lastName (Person _ lastname _ _ _ _) = lastname

age :: Person -> Int

age (Person _ _ age _ _ _) = age

height :: Person -> Float

height (Person _ _ _ height _ _) = height

phoneNumber :: Person -> String

phoneNumber (Person _ _ _ _ number _) = number

flavor :: Person -> String

flavor (Person _ _ _ _ _ flavor) = flavor

Whew! I certainly did not enjoy writing that! But despite being very cumbersome and boring to write, this method works.

ghci> let guy = Person "Buddy" "Finklestein" 43 184.2 "526-2928" "Chocolate"

ghci> firstName guy

"Buddy"

ghci> height guy

184.2

ghci> flavor guy

"Chocolate"

“Still, there must be a better way!” you say. Well, no, there isn’t, sorry. Just kidding—there is. Hahaha!

Haskell gives us an alternative way to write data types. Here’s how we could achieve the same functionality with

Return Main Page Previous Page Next Page

®Online Book Reader