-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path5.InsertionSort.lhs
More file actions
92 lines (63 loc) · 2.43 KB
/
5.InsertionSort.lhs
File metadata and controls
92 lines (63 loc) · 2.43 KB
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
Again, all the stuff we need from before:
> {-# LANGUAGE MultiParamTypeClasses #-}
> {-# LANGUAGE FlexibleInstances #-}
> {-# LANGUAGE FunctionalDependencies #-}
> {-# LANGUAGE UndecidableInstances #-}
> data True
> data False
> data Zero
> data Succ n
> type One = Succ Zero
> type Three = Succ (Succ (Succ Zero))
> class Add a b c | a b -> c where
> add :: a -> b -> c
> instance Add Zero b b
> instance Add a b c => Add (Succ a) b (Succ c)
> class Mul a b c | a b -> c where
> mul :: a -> b -> c
> instance Mul Zero b Zero
> instance (Mul a b c, Add b c d) => Mul (Succ a) b d
> u = undefined
Constructors for the type-level list. Notice the type variables on the
left.
> data Nil = Nil deriving Show
> data Cons x xs = Cons deriving Show
For example, we can generate a descending sequence.
> class DownFrom n xs | n -> xs where
> downfrom :: n -> xs
The list of numbers that are 'down from 0' is the empty list
> instance DownFrom Zero Nil
If there is an instance of a list that is down from n, then we can
construct the list that is down from n + 1:
> instance DownFrom n xs => DownFrom (Succ n) (Cons n xs)
You can test this with the following command in ghci:
:type downfrom (u :: Three)
Notice that if you don't ask for the type, you will get an error since
we have no values.
For insertion sort, we also need comparisons:
> class Lte a b c | a b -> c where
> lte :: a -> b -> c
Zero is less than or equal to any natural number
> instance Lte Zero b True
Any successor is larger than zero.
> instance Lte (Succ n) Zero False
if a <= b, then a + 1 <= b + 1
> instance Lte a b c => Lte (Succ a) (Succ b) c
Test it like so:
:type lte (u :: Zero) (u :: One)
:type lte (u :: One) (u :: Zero)
Finally, the list functions we need for insertion sort:
> class Insert x xs ys | x xs -> ys where
> insert :: x -> xs -> ys
Anything inserted into the empty list is a singleton list:
> instance Insert x Nil (Cons x Nil)
> instance (Lte x1 x2 b, InsertCons b x1 x2 xs ys) => Insert x1 (Cons x2 xs) ys
Insert deals with inserting single elements, InsertCons deals with
combining lists
> class InsertCons b x1 x2 xs ys | b x1 x2 xs -> ys
> instance InsertCons True x1 x2 xs (Cons x1 (Cons x2 xs))
> instance Insert x1 xs ys => InsertCons False x1 x2 xs (Cons x2 ys)
> class Sort xs ys | xs -> ys where
> sort :: xs -> ys
> instance Sort Nil Nil
> instance (Sort xs ys, Insert x ys zs) => Sort (Cons x xs) zs