Haskell Crash Course Part II

Recap: Haskell Crash Course II

  • Core program element is an expression
  • Every valid expression has a type (determined at compile-time)
  • Every valid expression reduces to a value (computed at run-time)










Recap: Haskell

Basic values & operators

  • Int, Bool, Char, Double
  • +, -, ==, /=

Execution / Function Calls

  • Just substitute equals by equals

Producing Collections

  • Pack data into tuples & lists

Consuming Collections

  • Unpack data via pattern-matching










Next: Creating and Using New Data Types

  1. type Synonyms: Naming existing types

  2. data types: Creating new types










Type Synonyms

Synonyms are just names (“aliases”) for existing types

  • think typedef in C










A type to represent Circle

A tuple (x, y, r) is a circle with center at (x, y) and radius r











A type to represent Cuboid

A tuple (length, depth, height) is a cuboid










Using Type Synonyms

We can now use synonyms by creating values of the given types

And we can write functions over synonyms too

We should get this behavior










QUIZ

Suppose we have the definitions

What is the result of

A. 0

B. Type error










Beware!

Type Synonyms

  • Do not create new types

  • Just name existing types

And hence, synonyms

  • Do not prevent confusing different values










Creating New Data Types

We can avoid mixing up by creating new data types

Constructors are the only way to create values

  • MkCircle creates CircleT

  • MkCuboid creates CuboidT










QUIZ

Suppose we create a new type with a data definition

What is the type of the MkCircle constructor?

A. MkCircle :: CircleT

B. MkCircle :: Double -> CircleT

C. MkCircle :: Double -> Double -> CircleT

D. MkCircle :: Double -> Double -> Double -> CircleT

E. MkCircle :: (Double, Double, Double) -> CircleT










Constructing Data

Constructors let us build values of the new type










QUIZ

Suppose we have the definitions

What is the result of

A. 6000

B. Type error










Deconstructing Data

Constructors let us build values of new type … but how to use those values?

How can we implement a function

such that










Deconstructing Data by Pattern Matching

Haskell lets us deconstruct data via pattern-matching

case e of Ctor x y z -> e1 is read as as

IF - e evaluates to a value that matches the pattern Ctor vx vy vz

THEN - evaluate e1 after naming x := vx, y := vy, z := vz










Pattern matching on Function Inputs

Very common to do matching on function inputs

So Haskell allows a nicer syntax: patterns in the arguments

Nice syntax plus the compiler saves us from mixing up values!










But … what if we need to mix up values?

Suppose I need to represent a list of shapes

  • Some Circles
  • Some Cuboids

What is the problem with shapes as defined below?

Where we have defined










Problem: All list elements must have the same type

Solution???











QUIZ: Variant (aka Union) Types

Lets create a single type that can represent both kinds of shapes!



What is the type of MkCircle 0 0 100 ?

A. Shape

B. Circle

C. (Double, Double, Double)







Each Data Constructor of Shape has a different type

When we define a data type like the below

We get multiple constructors for Shape

Now we can create collections of Shape

Now we can define

and then define collections of Shapes







EXERCISE

Lets define a type for 2D shapes

Write a function to compute the area of a Shape2D

HINT

Area of a polygon
Area of a polygon

You may want to use this helper that computes the area of a triangle at v1, v2, v3