Data Types with Parameters

Maybe takes in a type before creating a new type. Generalize that idea.

The Maybe “data type” has a definition like this:

data Maybe a = Nothing | Just a

This means that putting in types gives out different data types:

data Maybe Double = Nothing | Just Double
data Maybe String = Nothing | Just String

(Warning: these are not legal Haskell; to make them legal, make the left side one word like Maybe_Double.)

The Maybe type is built in, but anyone can make a data type that has a similar unknown parameter.

  1. Make three different instances of Triple Int, one for each possibility.

     data Triple a = Never | Unlikely a | Surely a
    
  2. It is allowed to have types on the right that never appear on the left. Those are always present; only the a type can vary. (See Types vs Constructors below.)

     data ProbablyL a = Never | ProbablyR Double a
    

    Make two examples of ProbablyL String.

  3. Write your own data definition and examples for a type Twin so that all of the following work:

    1. Both of these variables could be instances of Twin Double.

      a1 = Twin 1.5 4.5 a2 = NotPresent

    2. Make it possible for these to be instances of Twin String:

      b1 = Twin “Forward” “Backward” b2 = NotPresent

    3. Make it not possible to make Twin 0.5 "half".

Types vs Constructors

The standard Maybe data definition has a “pun” - it uses the same word for two different meanings. The word Maybe on the left is part of a type, while the Maybe on the right is called a constructor.

data Maybe a = Nothing | Maybe a

Changing the names will help clarify:

data MaybeL a = Nothing | MaybeR a

Now write a function fixer that takes in a Maybe Int and puts out an Int, giving 0 in the case of Nothing. Notice which version of Maybe is used in the type signature and which is used to access the value.

fixer :: MaybeL Int -> Int
fixer (MaybeR x) = x
fixer Nothing = 0

The pun is not very confusing when the left and right sides have the same number of arguments, but when they don’t watch out!

Types vs Constructors II

Consider the example type “Concern”, which takes in a single type variable. The idea is that whatever the “concern” is, it will be accompanied by an int indicating how big of a concern.

data ConcernL a = ConcernR Int a
    deriving (Show)

Exercises:

  1. A String concern has the string “leaky ceiling” and the value for the level of concern is 80.

    1. Create a variable holding this example.
    2. Write the type signature for that variable.
  2. A function is supposed to take a list of concerns and output a list of those whose level of concern is at least 50.

    1. Write the type signature for this function.
    2. Write the function.
    3. Make up a few more examples like the one above so you can test your function.