-
Notifications
You must be signed in to change notification settings - Fork 0
/
17typeClasses.hs
155 lines (99 loc) · 4.06 KB
/
17typeClasses.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
-- let us say we want to write an increment fxn which works on a variety of numerical types
-- it is entirely possible if we do not specify the type signature.
-- But can we write a type signature for a fxn "increment" which works on all numbers.
{-
*Main> :t (+)
(+) :: Num a => a -> a -> a
When we ask Haskell for the type of (+),
there are a few additional symbols in there:
Num a =>
This is a type class.
It means that 'a' is a type of of class Num.
What does that mean?
"Num" is a type class generalizing the idea of a number.
And all types of a class Num must have a function (+) defined on them.
We get more information from:
:info Num
which lists out all the functions that all members of the class Num.
All types that are a Num must must implement these functions
and the type signature of all these methods.
/ is not there because / is not defined on all cases of Num
-}
{-
*** Why do we need type classes at all? ***
If we dont have type classes, for example:
for each type we would need a different add function
like one with Double -> Double ->Double, Int -> Int -> Int
Infact,
We can use type classes to define functions which work on a variety of types.
-}
-- here, a is a type of class Num
-- and, this fxn accepts two Nums of type "a", and returns a type "a"
addThenMultiply :: Num a => a -> a -> a
addThenMultiply num1 num2 = ( num1 + num2 ) * 2
-- GHCI examples,
-- addThenMultiply 3 2.000
-- addThenMultiply 3 2
----------------------------------------------------------------------------
---------------------- Defining a type class -------------------------------
-- output of :info Num is the definition of the type class Num
{-
class MyNum a where
(+) :: a -> a -> a
(-) :: a -> a -> a
(*) :: a -> a -> a
-}
-- definiting our own type class Describable
class Describable a where
describe :: a -> String
-- ?? what do I do with Describable now?
----------------------------------------------------------------------------
---------------------- Common type classes ---------------------------------
-- Ord is a type class which:
-- "represents all of the things in the universe that can be compared and ordered. "
-- if we use :info <type>, example: :info Int, we get all the type classes for which Int is a member of
-- Show and Read are also type classes which implement the functions show and read.
-- any time a value is printed to the ghci it is because it is a memeber of the type Show
-- for types which have not implemented show, will not be able to print to the console
-- Example:
data Icecream = Chocolate | Vanilla
-- Icecream is nearly identical to Bool
-- but Bool implements show, and Icecream does not
-- this is not working :
{-
showme :: Show Icecream => Icecream -> String
showme Chocolate = "Chocolate"
showme Vanilla = "Vanilla"
-}
instance Show Icecream where
show Chocolate = "Chocolate"
show Vanilla = "Vanilla"
-- boom
-- earlier it used to say:
{-
<interactive>:451:1: error:
• No instance for (Show Icecream) arising from a use of ‘print’
• In a stmt of an interactive GHCi command: print it
-}
-- so I created an instance
------------------------ Deriving type classes --------------------
-- we can certainly derive from a type class too
-- we can derive Show into our custom type like this:
data ChildTypeRandom = RandomOne | RandomTwo deriving (Show, Eq, Ord)
data MyRandomType = MyRandomType ChildTypeRandom deriving (Show)
-- Haskell automatically implemented the type class Show for us here
z = MyRandomType RandomOne
--- MyRandomType RandomOne
-- 13.2
-- Soln: for inc created manually, if you give it the maxBound :: Int, it returns some value,
-- But succ that is implemented by Num etc, gives us an error
{-
Write the following function that works
just like succ on Bounded types but can
be called an unlimited number of times without error.
The function will work like inc in the preceding example
but works on a wider range of types,
including types that aren’t members of Num:
-}
cycleSucc :: (Bounded a, Enum a, Eq a) => a -> a
cycleSucc n = n -- ????