SlideShare a Scribd company logo
Real World Haskell:
     Lecture 4

   Bryan O’Sullivan


     2009-10-29
Quaternions


   A quaternion is a mathematical structure, “the extension of
   complex numbers to three dimensions.”
   In mathematical notation, some people write a quaternion q as
   follows:
                         q = a + bi + cj + dk

   The i, j, and k terms (the basis elements) are related to the ι of
   complex numbers, and have similarly weird properties:

                        i2 = j2 = k2 = ijk = −1
What are quaternions for?

       Invented in 1843 by William Rowan Hamilton.
       Briefly used in 19th-century physics, e.g. in the description of
       Maxwell’s equations that related electric and magnetic fields
       to charge density and current density.
       Lost favour in the 1890s, supplanted by vector analysis.
       Recently popular again, due to utility in describing rotations.

   Current uses include:
       Computer graphics (smoothly interpolated rotations)
       Signal processing (image disparity, e.g. in geophysics)
       Attitude control (e.g. in spacecraft)
       Orbital mechanics
       Simulation of molecular dynamics
What’s this got to do with Haskell?

   The set H of quaternions is equal to R4 (a 4d vector space over
   the reals), so we could conceivably use a representation like this:

   type Q u a t e r n i o n =
        ( Double , Double , Double , Double )

   Quaternions are not arbitrary 4-vectors; they have special
   properties.
   So why might we not want to use this definition?
       Since Quaternion is simply a synonym for a 4-tuple of
       Doubles, the compiler will treat the two types as the same,
       even when our intended meaning is distinct.
Giving types more structure


   We conclude that we want a quaternion to somehow “look
   different” from a 4-tuple. Here’s how we can do it:

   data Q u a t e r n i o n =
        Q Double Double Double Double

   The data directive introduces a completely new type named
   Quaternion.
   We call the name that follows the data directive the type
   constructor: it identifies the type.
Data constructors



   data Q u a t e r n i o n =
        Q Double Double Double Double

   Following the “=” sign above is the name Q, which is a data
   constructor for the Quaternion type.
   We use a data constructor to build a new value of a given type.
   Type constructors create types. Data constructors create values.
Using constructors (I)


   The 4 instances of Double following the Q are the type
   parameters to that data constructor.
   When we use our data constructor, we need to supply values:
       The number of values must match the number of type
       parameters.
       The type of each value must match the type parameter at
       that position.

   We have a simple case here: just plug in four numbers.
   zero = Q 0 0 0 0
Using constructors (II)
   Remember the data constructors for lists?
   (:)   : : a −> [ a ] −> [ a ]
   []    :: [a]
Using constructors (II)
   Remember the data constructors for lists?
   (:)   : : a −> [ a ] −> [ a ]
   []    :: [a]

   We use data constructors to create new values.
   foo = ’ f ’ : ’o ’ : ’o ’ : [ ]
Using constructors (II)
   Remember the data constructors for lists?
   (:)   : : a −> [ a ] −> [ a ]
   []    :: [a]

   We use data constructors to create new values.
   foo = ’ f ’ : ’o ’ : ’o ’ : [ ]

   We use type constructors in type signatures.
   stripLeft     : : [ Char ] −> [ Char ]
Using constructors (II)
   Remember the data constructors for lists?
   (:)   : : a −> [ a ] −> [ a ]
   []    :: [a]

   We use data constructors to create new values.
   foo = ’ f ’ : ’o ’ : ’o ’ : [ ]

   We use type constructors in type signatures.
   stripLeft     : : [ Char ] −> [ Char ]

   We pattern match against data constructors to inspect a value.
   s t r i p L e f t ( x : xs ) | isSpace x = s t r i p L e f t xs
                                | otherwise = x : xs
   stripLeft []                             = []
Using data constructors (III)



   We do the same with our new Quaternion type.
   Here’s a type signature for the function that creates a
   scalar-valued quaternion. Notice the use of the type constructor.
   s c a l a r : : Double −> Q u a t e r n i o n

   And here’s the definition of the scalar function, where we use the
   data constructor to create a new value of type Quaternion.
   scalar s = Q s 0 0 0
Using data constructors (IV)


   We perform pattern matching as you might expect:
   s c a l a r P a r t : : Q u a t e r n i o n −> Double
   scalarPart              (Q s               ) = s

   The special pattern “ ” above has the following meaning:
       “I don’t care what’s at this position. Don’t inspect the value
       here, and don’t bind it to a name.”
       In other words, it’s a wild card.
Using data constructors (IV)


   We perform pattern matching as you might expect:
   s c a l a r P a r t : : Q u a t e r n i o n −> Double
   scalarPart              (Q s               ) = s

   The special pattern “ ” above has the following meaning:
       “I don’t care what’s at this position. Don’t inspect the value
       here, and don’t bind it to a name.”
       In other words, it’s a wild card.

   Notice that we had to provide four patterns after the Q, one to
   match each of the Q constructor’s parameters.
Spelunking with the interpreter

   We can usefully inspect our new type in ghci:

   Prelude> :info Quaternion
   data Quaternion = Q Double Double Double Double
      -- Defined at Quaternion.hs:1:5-14

   The :info command is very useful! It tells us everything ghci
   knows about an identifier (regardless of whether it’s a type, a
   function, or whatever).
Spelunking with the interpreter

   We can usefully inspect our new type in ghci:

   Prelude> :info Quaternion
   data Quaternion = Q Double Double Double Double
      -- Defined at Quaternion.hs:1:5-14

   The :info command is very useful! It tells us everything ghci
   knows about an identifier (regardless of whether it’s a type, a
   function, or whatever).

   We can also inspect the type of the Q data constructor:

   Prelude> :type Q
   Q :: Double -> Double -> Double -> Double
     -> Quaternion
What does this correspond to?

   Are you struggling to follow so far?
What does this correspond to?

   Are you struggling to follow so far?

   Here’s an approximate equivalent to what we just covered, in a
   familiar language:

   struct quaternion {
       double a, b, c, d;
   };
What does this correspond to?

   Are you struggling to follow so far?

   Here’s an approximate equivalent to what we just covered, in a
   familiar language:

   struct quaternion {
       double a, b, c, d;
   };

   And here’s another, in a different (but still familiar) language:

   class Quaternion(object):
       def __init__(self, a,b,c,d):
           self.a,self.b,self.c,self.d = a,b,c,d
Comparing quaternions

   We’re used to being able to compare values.
   ( ” f o o ” == ” b a r ” , ” baz ” /= ” quux ” )
      == ( False , True )
           >

   So how should we compare quaternions? This definition won’t
   compile:
   w t f = s c a l a r 1 == s c a l a r 2

   Ugh, okay. Let’s try this:
   e q u a l s (Q a b c d ) (Q w x y z ) =
      a == w && b == x && c == y && d == z
Notational aside: functions and operators

   Functions and operators are the same, save for fixity. We usually
   apply functions in prefix position, and operators in infix position.
   However, we can treat an operator as a function by wrapping it in
   parentheses:
   (+) 1 2
   (:) ’a ’ [ ]
   zipWith (+) [ 1 , 2 , 3 ] [ 4 , 5 , 6 ]

   We can also apply a function as if it was an operator, by wrapping
   it in backquotes:
   s c a l a r 1 ‘ equals ‘     scalar 2
   ” wtf ”       ‘ isPrefixOf ‘ ” wtfbbq ”
But still. . . ugh!



    It seems lame that we can write this for strings:
    ” f o o ” == ” b a r ”

    And, even with our shiny new infix syntax, find ourselves stuck
    writing code like this for quaternions:
    s c a l a r 2 ‘ equals ‘ s c a l a r 3.14159265

    Surely there’s some kind of unifying principle we could put to work?
Enter the typeclass


   Here is a definition of a widely used typeclass:
   c l a s s Eq a where
           (==) : : a −> a −> Bool
   The definition says “there is a class of types that support a
   function named (==).”
Enter the typeclass


   Here is a definition of a widely used typeclass:
   c l a s s Eq a where
           (==) : : a −> a −> Bool
   The definition says “there is a class of types that support a
   function named (==).”

   How can we declare a type as being a member of this Eq class?
   i n s t a n c e Eq Q u a t e r n i o n where
           (==) = e q u a l s
   This means “any time someone asks for the (==) function on
   Quaternion type, use the equals function.”
Use of (==)


  As we know, we can use the (==) operator when writing functions:
   elem a [ ]              = False
   elem a ( x : x s )
       | a == x            = True
       | o t h e r w i s e = elem a x s

  Notice something very important:
       This function needs to know almost nothing about the type of
       the values a and x.
       It’s enough to know that the type supports the (==)
       function, i.e. that it’s an instance of the Eq typeclass.
Bounded polymorphism



  The elem function is clearly polymorphic, but it’s not fully
  polymorphic.
      It will work for any instance of Eq.
      However, it will not work on types that are not instances of
      Eq, since they don’t supply an implementation of (==).
      So our function exhibits a special kind of polymorphism called
      bounded (or constrained) polymorphism.
Expressing bounded polymorphism

   We can express the fact that elem only accepts instances of Eq in
   its type signature:
   elem : : ( Eq a ) = a −> [ a ] −> Bool
                      >
   The “(Eq a) =>” part of the signature is called a constraint.
   In the absence of a type signature, a Haskell compiler will infer the
   presence of any necessary constraints.
Expressing bounded polymorphism

   We can express the fact that elem only accepts instances of Eq in
   its type signature:
   elem : : ( Eq a ) = a −> [ a ] −> Bool
                      >
   The “(Eq a) =>” part of the signature is called a constraint.
   In the absence of a type signature, a Haskell compiler will infer the
   presence of any necessary constraints.


   Aside: Haskell’s kind of polymorphism is called parametric. In this
   type signature:
   (++) : : [ a ] −> [ a ] −> [ a ]
   The type of (++) is parameterized by the type variable a.
Rainbows, oh my!

   Suppose we want to refer to symbolic values.
   data Rainbow = Red | Orange | Y e l l o w | Green
                | Blue | I n d i g o | V i o l e t
   We have defined a type Rainbow with a whole pile of data
   constructors.
       These constructors are all independent.
       If you’re a C or C++ hacker, think of Rainbow as an
       enumerated type (enum).
       Each data constructor creates a value of type Rainbow.
       We can pattern match against a value to see whether it is
       Green, or Blue, or whatever.
Showing your work


   We haven’t indicated how to print values from our new datatypes
   yet. Indeed, unless we do something explicit, we can’t print them.
   Fortunately for us, there’s a Show typeclass, with a useful function:
   show : : (Show a ) = a −> S t r i n g
                       >

   So. What do we do?
   i n s t a n c e Show Rainbow where
           show Red       = ”Red”
           show Green = ” Green ”
           {− . . . e t c . . . −}
Yeuch!



   That’s some serious drudgery there. I hate repeating myself.
   Fortunately, for some key typeclasses, Haskell can automatically
   derive instances for us as follows.

   data Rainbow = Red | Orange | Y e l l o w | Green
                       | Blue | I n d i g o | V i o l e t
        d e r i v i n g ( Eq , Ord , Bounded , Enum, Show)

   This saves a lot of meaningless finger-plonkulating.
Homework (I)—the trivial part




   Use ghci to investigate the Ord, Bounded, and Enum
   typeclasses.
Homework (II)



   Three non-overlapping points in the plane R2 form either an acute
   angle (< 180◦ ), a straight line, or an obtuse angle (> 180◦ ).

   Define a type that represents these possibilities.

   Write a type signature for a function that accepts three points, and
   categorises them in this fashion.

   Now write the function itself.
Homework (III)

   In computational geometry, the convex hull of a set of
   non-overlapping points is the minimal bounding polygon for which
   all angles are acute.




   Using your categorisation function, write a function that computes
   the convex hull of a set of points.

   (If you need a hint, look up “Graham’s scan algorithm”.)

More Related Content

PDF
Real World Haskell: Lecture 2
PDF
Real World Haskell: Lecture 5
PDF
Real World Haskell: Lecture 3
PDF
Real World Haskell: Lecture 6
PDF
Real World Haskell: Lecture 1
PDF
Real World Haskell: Lecture 7
PDF
Scala 3 enum for a terser Option Monad Algebraic Data Type
PDF
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit - Haskell and...
Real World Haskell: Lecture 2
Real World Haskell: Lecture 5
Real World Haskell: Lecture 3
Real World Haskell: Lecture 6
Real World Haskell: Lecture 1
Real World Haskell: Lecture 7
Scala 3 enum for a terser Option Monad Algebraic Data Type
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit - Haskell and...

What's hot (20)

PDF
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
PDF
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - with ...
PDF
The Functional Programming Triad of Folding, Scanning and Iteration - a first...
PDF
High-Performance Haskell
PDF
Functional Programming by Examples using Haskell
PDF
Haskell for data science
PDF
Monad Transformers - Part 1
PDF
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit – Haskell and...
PDF
Lambda? You Keep Using that Letter
PDF
Left and Right Folds - Comparison of a mathematical definition and a programm...
PDF
Sequence and Traverse - Part 3
PDF
Addendum to ‘Monads do not Compose’
PDF
The Functional Programming Triad of Folding, Scanning and Iteration - a first...
PDF
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 5
PDF
Monad Fact #4
PDF
The Functional Programming Triad of Map, Filter and Fold
PDF
Sequence and Traverse - Part 2
PDF
Monoids - Part 1 - with examples using Scalaz and Cats
PDF
Abstracting over the Monad yielded by a for comprehension and its generators
PDF
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - with ...
The Functional Programming Triad of Folding, Scanning and Iteration - a first...
High-Performance Haskell
Functional Programming by Examples using Haskell
Haskell for data science
Monad Transformers - Part 1
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit – Haskell and...
Lambda? You Keep Using that Letter
Left and Right Folds - Comparison of a mathematical definition and a programm...
Sequence and Traverse - Part 3
Addendum to ‘Monads do not Compose’
The Functional Programming Triad of Folding, Scanning and Iteration - a first...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 5
Monad Fact #4
The Functional Programming Triad of Map, Filter and Fold
Sequence and Traverse - Part 2
Monoids - Part 1 - with examples using Scalaz and Cats
Abstracting over the Monad yielded by a for comprehension and its generators
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part ...
Ad

Viewers also liked (20)

PPT
Classic I Romantic
PDF
Pothiz july-2010
ODP
Dexma project plm
PPSX
Ave+MaríA..
PPT
Fball Gibbs Alex Gibbs Zone Coaching Points
PDF
Measuring Social Media 20091022
PDF
CUFP 2009 Keynote - Real World Haskell
PDF
TRG – Social Media For Retailers
PDF
사료이야기 동지는 간 데 없고 깃발은 찢겨져
PPTX
Desafios para o uso de TICs aplicadas à educação
PDF
Constitution of india
PPTX
PCRS Ewa Bialek Sybiracy Swidwin
PPT
UOM 2012
PPT
Ple2012
PDF
Современный инжиниринг. Особенности и тенденции.
PPTX
Comparing US and Spanish student teachers' perceptions on Social Media
PDF
Swidwin-1960-1990-Ewa-Bialek
PDF
GLBT ALMS 2008 program
PPTX
Freeu - How to Create a Course
PPT
Blogs, Privacy, and User-generated Content
Classic I Romantic
Pothiz july-2010
Dexma project plm
Ave+MaríA..
Fball Gibbs Alex Gibbs Zone Coaching Points
Measuring Social Media 20091022
CUFP 2009 Keynote - Real World Haskell
TRG – Social Media For Retailers
사료이야기 동지는 간 데 없고 깃발은 찢겨져
Desafios para o uso de TICs aplicadas à educação
Constitution of india
PCRS Ewa Bialek Sybiracy Swidwin
UOM 2012
Ple2012
Современный инжиниринг. Особенности и тенденции.
Comparing US and Spanish student teachers' perceptions on Social Media
Swidwin-1960-1990-Ewa-Bialek
GLBT ALMS 2008 program
Freeu - How to Create a Course
Blogs, Privacy, and User-generated Content
Ad

Similar to Real World Haskell: Lecture 4 (20)

PDF
07. haskell Membership
PDF
Why Haskell Matters
KEY
An Introduction to Functional Programming using Haskell
ODP
06. haskell type builder
PDF
The Next Great Functional Programming Language
PDF
09. haskell Context
PDF
Ds lab handouts
PDF
Regular types in C++
PDF
12TypeSystem.pdf
PDF
Functional Programming in C++
PDF
10. haskell Modules
PDF
Container and algorithms(C++)
PPT
haskell5.ppt is a marketing document lol
PDF
Scala Functional Patterns
PDF
Power of functions in a typed world
PPT
chapter7.ppt java programming lecture notes
PPTX
Dependent Types with Idris
PDF
Session2
PDF
Introduction to Functional Languages
PDF
Modular Module Systems
07. haskell Membership
Why Haskell Matters
An Introduction to Functional Programming using Haskell
06. haskell type builder
The Next Great Functional Programming Language
09. haskell Context
Ds lab handouts
Regular types in C++
12TypeSystem.pdf
Functional Programming in C++
10. haskell Modules
Container and algorithms(C++)
haskell5.ppt is a marketing document lol
Scala Functional Patterns
Power of functions in a typed world
chapter7.ppt java programming lecture notes
Dependent Types with Idris
Session2
Introduction to Functional Languages
Modular Module Systems

Recently uploaded (20)

PDF
102 student loan defaulters named and shamed – Is someone you know on the list?
PPTX
Introduction_to_Human_Anatomy_and_Physiology_for_B.Pharm.pptx
PPTX
1st Inaugural Professorial Lecture held on 19th February 2020 (Governance and...
PDF
Sports Quiz easy sports quiz sports quiz
PDF
Supply Chain Operations Speaking Notes -ICLT Program
PDF
grade 11-chemistry_fetena_net_5883.pdf teacher guide for all student
PPTX
Cell Structure & Organelles in detailed.
PDF
01-Introduction-to-Information-Management.pdf
PDF
Physiotherapy_for_Respiratory_and_Cardiac_Problems WEBBER.pdf
PDF
Basic Mud Logging Guide for educational purpose
PPTX
school management -TNTEU- B.Ed., Semester II Unit 1.pptx
PDF
Module 4: Burden of Disease Tutorial Slides S2 2025
PPTX
IMMUNITY IMMUNITY refers to protection against infection, and the immune syst...
PDF
VCE English Exam - Section C Student Revision Booklet
PDF
Insiders guide to clinical Medicine.pdf
PDF
The Lost Whites of Pakistan by Jahanzaib Mughal.pdf
PPTX
Lesson notes of climatology university.
PDF
O5-L3 Freight Transport Ops (International) V1.pdf
PDF
2.FourierTransform-ShortQuestionswithAnswers.pdf
PDF
3rd Neelam Sanjeevareddy Memorial Lecture.pdf
102 student loan defaulters named and shamed – Is someone you know on the list?
Introduction_to_Human_Anatomy_and_Physiology_for_B.Pharm.pptx
1st Inaugural Professorial Lecture held on 19th February 2020 (Governance and...
Sports Quiz easy sports quiz sports quiz
Supply Chain Operations Speaking Notes -ICLT Program
grade 11-chemistry_fetena_net_5883.pdf teacher guide for all student
Cell Structure & Organelles in detailed.
01-Introduction-to-Information-Management.pdf
Physiotherapy_for_Respiratory_and_Cardiac_Problems WEBBER.pdf
Basic Mud Logging Guide for educational purpose
school management -TNTEU- B.Ed., Semester II Unit 1.pptx
Module 4: Burden of Disease Tutorial Slides S2 2025
IMMUNITY IMMUNITY refers to protection against infection, and the immune syst...
VCE English Exam - Section C Student Revision Booklet
Insiders guide to clinical Medicine.pdf
The Lost Whites of Pakistan by Jahanzaib Mughal.pdf
Lesson notes of climatology university.
O5-L3 Freight Transport Ops (International) V1.pdf
2.FourierTransform-ShortQuestionswithAnswers.pdf
3rd Neelam Sanjeevareddy Memorial Lecture.pdf

Real World Haskell: Lecture 4

  • 1. Real World Haskell: Lecture 4 Bryan O’Sullivan 2009-10-29
  • 2. Quaternions A quaternion is a mathematical structure, “the extension of complex numbers to three dimensions.” In mathematical notation, some people write a quaternion q as follows: q = a + bi + cj + dk The i, j, and k terms (the basis elements) are related to the ι of complex numbers, and have similarly weird properties: i2 = j2 = k2 = ijk = −1
  • 3. What are quaternions for? Invented in 1843 by William Rowan Hamilton. Briefly used in 19th-century physics, e.g. in the description of Maxwell’s equations that related electric and magnetic fields to charge density and current density. Lost favour in the 1890s, supplanted by vector analysis. Recently popular again, due to utility in describing rotations. Current uses include: Computer graphics (smoothly interpolated rotations) Signal processing (image disparity, e.g. in geophysics) Attitude control (e.g. in spacecraft) Orbital mechanics Simulation of molecular dynamics
  • 4. What’s this got to do with Haskell? The set H of quaternions is equal to R4 (a 4d vector space over the reals), so we could conceivably use a representation like this: type Q u a t e r n i o n = ( Double , Double , Double , Double ) Quaternions are not arbitrary 4-vectors; they have special properties. So why might we not want to use this definition? Since Quaternion is simply a synonym for a 4-tuple of Doubles, the compiler will treat the two types as the same, even when our intended meaning is distinct.
  • 5. Giving types more structure We conclude that we want a quaternion to somehow “look different” from a 4-tuple. Here’s how we can do it: data Q u a t e r n i o n = Q Double Double Double Double The data directive introduces a completely new type named Quaternion. We call the name that follows the data directive the type constructor: it identifies the type.
  • 6. Data constructors data Q u a t e r n i o n = Q Double Double Double Double Following the “=” sign above is the name Q, which is a data constructor for the Quaternion type. We use a data constructor to build a new value of a given type. Type constructors create types. Data constructors create values.
  • 7. Using constructors (I) The 4 instances of Double following the Q are the type parameters to that data constructor. When we use our data constructor, we need to supply values: The number of values must match the number of type parameters. The type of each value must match the type parameter at that position. We have a simple case here: just plug in four numbers. zero = Q 0 0 0 0
  • 8. Using constructors (II) Remember the data constructors for lists? (:) : : a −> [ a ] −> [ a ] [] :: [a]
  • 9. Using constructors (II) Remember the data constructors for lists? (:) : : a −> [ a ] −> [ a ] [] :: [a] We use data constructors to create new values. foo = ’ f ’ : ’o ’ : ’o ’ : [ ]
  • 10. Using constructors (II) Remember the data constructors for lists? (:) : : a −> [ a ] −> [ a ] [] :: [a] We use data constructors to create new values. foo = ’ f ’ : ’o ’ : ’o ’ : [ ] We use type constructors in type signatures. stripLeft : : [ Char ] −> [ Char ]
  • 11. Using constructors (II) Remember the data constructors for lists? (:) : : a −> [ a ] −> [ a ] [] :: [a] We use data constructors to create new values. foo = ’ f ’ : ’o ’ : ’o ’ : [ ] We use type constructors in type signatures. stripLeft : : [ Char ] −> [ Char ] We pattern match against data constructors to inspect a value. s t r i p L e f t ( x : xs ) | isSpace x = s t r i p L e f t xs | otherwise = x : xs stripLeft [] = []
  • 12. Using data constructors (III) We do the same with our new Quaternion type. Here’s a type signature for the function that creates a scalar-valued quaternion. Notice the use of the type constructor. s c a l a r : : Double −> Q u a t e r n i o n And here’s the definition of the scalar function, where we use the data constructor to create a new value of type Quaternion. scalar s = Q s 0 0 0
  • 13. Using data constructors (IV) We perform pattern matching as you might expect: s c a l a r P a r t : : Q u a t e r n i o n −> Double scalarPart (Q s ) = s The special pattern “ ” above has the following meaning: “I don’t care what’s at this position. Don’t inspect the value here, and don’t bind it to a name.” In other words, it’s a wild card.
  • 14. Using data constructors (IV) We perform pattern matching as you might expect: s c a l a r P a r t : : Q u a t e r n i o n −> Double scalarPart (Q s ) = s The special pattern “ ” above has the following meaning: “I don’t care what’s at this position. Don’t inspect the value here, and don’t bind it to a name.” In other words, it’s a wild card. Notice that we had to provide four patterns after the Q, one to match each of the Q constructor’s parameters.
  • 15. Spelunking with the interpreter We can usefully inspect our new type in ghci: Prelude> :info Quaternion data Quaternion = Q Double Double Double Double -- Defined at Quaternion.hs:1:5-14 The :info command is very useful! It tells us everything ghci knows about an identifier (regardless of whether it’s a type, a function, or whatever).
  • 16. Spelunking with the interpreter We can usefully inspect our new type in ghci: Prelude> :info Quaternion data Quaternion = Q Double Double Double Double -- Defined at Quaternion.hs:1:5-14 The :info command is very useful! It tells us everything ghci knows about an identifier (regardless of whether it’s a type, a function, or whatever). We can also inspect the type of the Q data constructor: Prelude> :type Q Q :: Double -> Double -> Double -> Double -> Quaternion
  • 17. What does this correspond to? Are you struggling to follow so far?
  • 18. What does this correspond to? Are you struggling to follow so far? Here’s an approximate equivalent to what we just covered, in a familiar language: struct quaternion { double a, b, c, d; };
  • 19. What does this correspond to? Are you struggling to follow so far? Here’s an approximate equivalent to what we just covered, in a familiar language: struct quaternion { double a, b, c, d; }; And here’s another, in a different (but still familiar) language: class Quaternion(object): def __init__(self, a,b,c,d): self.a,self.b,self.c,self.d = a,b,c,d
  • 20. Comparing quaternions We’re used to being able to compare values. ( ” f o o ” == ” b a r ” , ” baz ” /= ” quux ” ) == ( False , True ) > So how should we compare quaternions? This definition won’t compile: w t f = s c a l a r 1 == s c a l a r 2 Ugh, okay. Let’s try this: e q u a l s (Q a b c d ) (Q w x y z ) = a == w && b == x && c == y && d == z
  • 21. Notational aside: functions and operators Functions and operators are the same, save for fixity. We usually apply functions in prefix position, and operators in infix position. However, we can treat an operator as a function by wrapping it in parentheses: (+) 1 2 (:) ’a ’ [ ] zipWith (+) [ 1 , 2 , 3 ] [ 4 , 5 , 6 ] We can also apply a function as if it was an operator, by wrapping it in backquotes: s c a l a r 1 ‘ equals ‘ scalar 2 ” wtf ” ‘ isPrefixOf ‘ ” wtfbbq ”
  • 22. But still. . . ugh! It seems lame that we can write this for strings: ” f o o ” == ” b a r ” And, even with our shiny new infix syntax, find ourselves stuck writing code like this for quaternions: s c a l a r 2 ‘ equals ‘ s c a l a r 3.14159265 Surely there’s some kind of unifying principle we could put to work?
  • 23. Enter the typeclass Here is a definition of a widely used typeclass: c l a s s Eq a where (==) : : a −> a −> Bool The definition says “there is a class of types that support a function named (==).”
  • 24. Enter the typeclass Here is a definition of a widely used typeclass: c l a s s Eq a where (==) : : a −> a −> Bool The definition says “there is a class of types that support a function named (==).” How can we declare a type as being a member of this Eq class? i n s t a n c e Eq Q u a t e r n i o n where (==) = e q u a l s This means “any time someone asks for the (==) function on Quaternion type, use the equals function.”
  • 25. Use of (==) As we know, we can use the (==) operator when writing functions: elem a [ ] = False elem a ( x : x s ) | a == x = True | o t h e r w i s e = elem a x s Notice something very important: This function needs to know almost nothing about the type of the values a and x. It’s enough to know that the type supports the (==) function, i.e. that it’s an instance of the Eq typeclass.
  • 26. Bounded polymorphism The elem function is clearly polymorphic, but it’s not fully polymorphic. It will work for any instance of Eq. However, it will not work on types that are not instances of Eq, since they don’t supply an implementation of (==). So our function exhibits a special kind of polymorphism called bounded (or constrained) polymorphism.
  • 27. Expressing bounded polymorphism We can express the fact that elem only accepts instances of Eq in its type signature: elem : : ( Eq a ) = a −> [ a ] −> Bool > The “(Eq a) =>” part of the signature is called a constraint. In the absence of a type signature, a Haskell compiler will infer the presence of any necessary constraints.
  • 28. Expressing bounded polymorphism We can express the fact that elem only accepts instances of Eq in its type signature: elem : : ( Eq a ) = a −> [ a ] −> Bool > The “(Eq a) =>” part of the signature is called a constraint. In the absence of a type signature, a Haskell compiler will infer the presence of any necessary constraints. Aside: Haskell’s kind of polymorphism is called parametric. In this type signature: (++) : : [ a ] −> [ a ] −> [ a ] The type of (++) is parameterized by the type variable a.
  • 29. Rainbows, oh my! Suppose we want to refer to symbolic values. data Rainbow = Red | Orange | Y e l l o w | Green | Blue | I n d i g o | V i o l e t We have defined a type Rainbow with a whole pile of data constructors. These constructors are all independent. If you’re a C or C++ hacker, think of Rainbow as an enumerated type (enum). Each data constructor creates a value of type Rainbow. We can pattern match against a value to see whether it is Green, or Blue, or whatever.
  • 30. Showing your work We haven’t indicated how to print values from our new datatypes yet. Indeed, unless we do something explicit, we can’t print them. Fortunately for us, there’s a Show typeclass, with a useful function: show : : (Show a ) = a −> S t r i n g > So. What do we do? i n s t a n c e Show Rainbow where show Red = ”Red” show Green = ” Green ” {− . . . e t c . . . −}
  • 31. Yeuch! That’s some serious drudgery there. I hate repeating myself. Fortunately, for some key typeclasses, Haskell can automatically derive instances for us as follows. data Rainbow = Red | Orange | Y e l l o w | Green | Blue | I n d i g o | V i o l e t d e r i v i n g ( Eq , Ord , Bounded , Enum, Show) This saves a lot of meaningless finger-plonkulating.
  • 32. Homework (I)—the trivial part Use ghci to investigate the Ord, Bounded, and Enum typeclasses.
  • 33. Homework (II) Three non-overlapping points in the plane R2 form either an acute angle (< 180◦ ), a straight line, or an obtuse angle (> 180◦ ). Define a type that represents these possibilities. Write a type signature for a function that accepts three points, and categorises them in this fashion. Now write the function itself.
  • 34. Homework (III) In computational geometry, the convex hull of a set of non-overlapping points is the minimal bounding polygon for which all angles are acute. Using your categorisation function, write a function that computes the convex hull of a set of points. (If you need a hint, look up “Graham’s scan algorithm”.)