Slide 1

Slide 1 text

PureScript Meetup #13 Introduction to Type Class CYBAI _cybai 1

Slide 2

Slide 2 text

Agenda • Introduction to Type Class • Common Type Class: Show, Eq, and Ord • Type Class: Semigroup, Monoid and Foldable • Derive • Comparison to Interface • References 2

Slide 3

Slide 3 text

Syntax 3 Name of Type Class Method of this type class Type Signature of the method class Eq a where eq :: a -> a -> Boolean `class` keyword to declare Type Class

Slide 4

Slide 4 text

Introduction to Type Class 4

Slide 5

Slide 5 text

– haskellbook, CH6 “Where a declaration of a type defines how that type in particular is created, a declaration of a typeclass defines how a set of types are consumed or used in computations.” 5

Slide 6

Slide 6 text

Introduction 6 If you know other programming languages with a similar concept, it may help to think of typeclasses as being like interfaces to data that can work across multiple datatypes. Ref: haskellbook, CH6 “The goal is to define a datatype by cases, where one can add new cases to the datatype and new functions over the datatype, without recompiling existing code, and while retaining static type safety (e.g., no casts).”

Slide 7

Slide 7 text

Let’s start from Common Type Class. 7

Slide 8

Slide 8 text

Common Type Class 8 What does this mean?

Slide 9

Slide 9 text

Common Type Class 9 This means our datatype doesn’t have instance of `Show` type class; thus, we need to instantiate Show for Browser datatype.

Slide 10

Slide 10 text

Common Type Class 10 Show Ref: Data.Show type class declaration

Slide 11

Slide 11 text

Common Type Class 11 Show instance showBrowser :: Show Browser where show Chrome = "Chrome" show Firefox = "Firefox" show Servo = "Servo" `instance` keyword to declare an instance of Type Class The Type Class of this instantiation The type provided for this instantiation `where` keyword terminates the initial declaration and beginning of the instance. Implement method(s) included in the Type Class

Slide 12

Slide 12 text

Common Type Class 12 Show After instantiated, your data type can be shown in REPL now.

Slide 13

Slide 13 text

Common Type Class 13 Eq Ref: Data.Eq type class declaration

Slide 14

Slide 14 text

Common Type Class 14 Eq When we define the type class method, we can only define the method with type signature. Type signature can make sure that we’ll always have same type though. However, we cannot guarantee correct logic for users. Thus, we can define laws for the type class and let user follow them.

Slide 15

Slide 15 text

Common Type Class 15 Eq Let’s have an insane example.

Slide 16

Slide 16 text

Common Type Class 16 Eq Let’s have an insane example. instance eqBrowser :: Eq Browser where eq Chrome Firefox = true eq Firefox Firefox = true eq _ _ = false Obviously, we can see Chrome is equal to Firefox but Firefox is not equal to Chrome.

Slide 17

Slide 17 text

Common Type Class 17 Eq Thus, when we’re instantiating type class for our datatypes, please prove it correctly. instance eqBrowser :: Eq Browser where eq Chrome Chrome = true eq Firefox Firefox = true eq Servo Servo = true eq _ _ = false

Slide 18

Slide 18 text

Common Type Class 18 Eq After implementing the `eq` correctly, now we can get correct and reasonable result from it.

Slide 19

Slide 19 text

Common Type Class 19 Ord Ref: Data.Ord type class declaration What’s the `Eq a` here?

Slide 20

Slide 20 text

Common Type Class 20 Ord class Eq a <= Ord a where compare :: a -> a -> Ordering Using `<=` in type class means superclass for the Type Class. It means `Eq` is a superclass of `Ord` so when you’d like to instantiate `Ord` for a datatype, you should confirm it has also instantiated `Eq`.

Slide 21

Slide 21 text

Common Type Class 21 Ord What will happen if we don’t instantiate `Eq` type class for the datatype when we’d like to instantiate `Ord`?

Slide 22

Slide 22 text

Common Type Class 22 Ord data Browser = Chrome | Firefox | Servo instance eqBrowser :: Eq Browser where eq Chrome Chrome = true eq Firefox Firefox = true eq Servo Servo = true eq _ _ = false instance ordBrowser :: Ord Browser where compare Servo Firefox = GT compare Servo Chrome = GT compare Firefox Chrome = GT compare a b | eq a b = EQ compare _ _ = LT Let’s use guard here to simplify for equality!

Slide 23

Slide 23 text

Common Type Class 23 Ord Then, we can compare `Ordering` of the datatype.

Slide 24

Slide 24 text

24 After introducing the three common ones, let’s continue with Foldable and its related Type Classes to get more familiar with Type Class! Semigroup, Monoid and Foldable

Slide 25

Slide 25 text

Type Class: Semigroup 25 Ref: Data.Semigroup type class declaration

Slide 26

Slide 26 text

Type Class: Semigroup 26 Ref: Pursuit of Semigroup The law of Semigroup

Slide 27

Slide 27 text

Type Class: Semigroup 27 As we saw the law in previous slides, it must be associative. So, if we’d like to make any type as an instance of Semigroup, remember to follow the law to instantiate it!

Slide 28

Slide 28 text

Type Class: Monoid 28 Ref: Data.Monoid type class declaration

Slide 29

Slide 29 text

Type Class: Monoid 29 Ref: Data.Monoid type class declaration How’s the law for Monoid?

Slide 30

Slide 30 text

Type Class: Monoid 30 Ref: Data.Monoid type class declaration • Left identity • Right identity

Slide 31

Slide 31 text

Type Class: Monoid 31 Ref: Data.Monoid type class declaration As a Monoid, we usually see it as a “Empty” value for your type.

Slide 32

Slide 32 text

Type Class: Monoid 32 Ref: Data.Monoid type class declaration For Example,

Slide 33

Slide 33 text

Type Class: Monoid 33 Ref: Data.Monoid type class declaration For Example, We can always have the original array no matter we do left append or right append with empty array.

Slide 34

Slide 34 text

Type Class: Monoid 34 Ref: Data.Monoid type class declaration For Example, We can always have the original array no matter we do left append or right append with empty array. We can always have same string no matter we do left concat or right concat with empty string.

Slide 35

Slide 35 text

Type Class: Foldable 35 Ref: Data.Foldable type class declaration

Slide 36

Slide 36 text

Type Class: Foldable 36 Ref: Data.Foldable type class declaration When we make a type as an instance of Foldable, it means the type can be folded.

Slide 37

Slide 37 text

Type Class: Foldable 37 Ref: Data.Foldable type class declaration

Slide 38

Slide 38 text

Type Class: Foldable 38 Ref: Data.Foldable type class declaration Member Methods foldr is same as reduceRight in JavaScript. foldl is same as reduce in JavaScript.

Slide 39

Slide 39 text

Type Class: Foldable 39 Ref: Data.Foldable type class declaration Member Methods How about foldMap?

Slide 40

Slide 40 text

Type Class: Foldable 40 Ref: Data.Foldable type class declaration Member Methods How about foldMap?

Slide 41

Slide 41 text

Type Class: Foldable 41 Ref: Data.Foldable type class declaration Member Methods How about foldMap? Looking at the type signature of foldMap. We can know the m argument must be a Monoid. So, we can handle the folding for the empty case via mempty. Let’s see an example with showing an array.

Slide 42

Slide 42 text

Type Class: Foldable 42 Ref: Data.Foldable type class declaration foldMap Example: Show an array with joined text With foldr or foldl, With foldMap,

Slide 43

Slide 43 text

Type Class: Foldable 43 Ref: Data.Foldable type class declaration foldMap Example: Show an array with joined text The first argument of foldMap is a function which takes a type a and return a Monoid m. And, show is a function which takes a type a and return a String which is a Monoid. foldMap implementation of Array is folding from mempty as a starting point; mempty of String is an empty String. So, we don’t need to pass the second argument like in foldl or foldr which is an empty String.

Slide 44

Slide 44 text

Type Class: Foldable 44 Ref: Data.Foldable type class declaration

Slide 45

Slide 45 text

Derive 45 When we use `derive`, compiler will instantiate the type class automatically. derive instance eqBrowser :: Eq Browser instance eqBrowser :: Eq Browser where eq Chrome Chrome = true eq Firefox Firefox = true eq Servo Servo = true eq _ _ = false Same

Slide 46

Slide 46 text

Derive (Cont.) 46 Ref: Type Class Deriving Currently supported derivable Type Class in PureScript

Slide 47

Slide 47 text

Comparison to Interface 47

Slide 48

Slide 48 text

Comparison to Interface 48 Different Types

Slide 49

Slide 49 text

Comparison to Interface 49 Different Types class Eq a <= Ord a where compare :: a -> a -> Ordering In PureScript / Haskell, via type signature, we can know that we’ll have same type, `a`, of arguments in `compare` function. Ref: How do type classes differ from interfaces?

Slide 50

Slide 50 text

50 Comparison to Interface Different Types public interface Ord extends Eq { public Ordering compare(Ord other); } public enum Ordering { LT, EQ, GT } public class OrdUtil { static bool lessThanOrEqual(A a1, A a2) { Ordering result = a1.compare(a2); return result == LT || result == EQ; } } In Java, we can `extends` Ord interface; however, it cannot make sure the type `A` are always same type. Ref: How do type classes differ from interfaces?

Slide 51

Slide 51 text

Comparison to Interface 51 Separation of Implementation

Slide 52

Slide 52 text

52 Comparison to Interface Ref: How do type classes differ from interfaces? Separation of Implementation Let’s assume this Large is from a upstream package.

Slide 53

Slide 53 text

53 Comparison to Interface Ref: How do type classes differ from interfaces? Separation of Implementation interface SomeOtherPackage { public bool doSomeThing(int lol); } public class MyLarge implements SomeOtherPackage { public final Large large; public MyLarge(Large large) { this.large = large; } public bool doSomething(int lol) { System.out.println("wut"); } } If we’d like to create our `interface`, we’ll need to create a new Class to wrap the `Large`.

Slide 54

Slide 54 text

54 Comparison to Interface Ref: How do type classes differ from interfaces? Separation of Implementation import JokesAreFun (ToyOrd( ..)) class MyNewClass a where doSomething :: a -> Int -> IO () instance MyNewClass ToyOrd where doSomething Smol x = putStrLn "hahahaa yess" doSomething (Large x) y = putStrLn ("numbers! " ++ show (x + y)) “Type classes separate the definition of data types and the instances of a class.” So, when we need to create our own type class and instantiate it for upstream package datatype, we can just make the datatype as one of instance of our new type class.

Slide 55

Slide 55 text

Q & A 55

Slide 56

Slide 56 text

Thank you! 56