-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTutorial.hs
232 lines (173 loc) · 6.46 KB
/
Tutorial.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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleInstances #-}
module Tutorial where
import Prelude hiding (Ord(..),Eq(..))
import qualified Prelude
import Data.Array
data FunC a where
LitI :: Int -> FunC Int
LitB :: Bool -> FunC Bool
While :: (FunC s -> FunC Bool) -> (FunC s -> FunC s) -> FunC s -> FunC s
If :: FunC Bool -> FunC a -> FunC a -> FunC a
Pair :: FunC a -> FunC b -> FunC (a,b)
Fst :: FunC (a,b) -> FunC a
Snd :: FunC (a,b) -> FunC b
Prim1 :: String -> (a -> b) -> FunC a -> FunC b
Prim2 :: String -> (a -> b -> c) -> FunC a -> FunC b -> FunC c
Arr :: FunC Int -> (FunC Int -> FunC a) -> FunC (Array Int a)
Undef :: FunC a
Value :: a -> FunC a
Variable :: String -> FunC a
eval :: FunC a -> a
eval (LitI i) = i
eval (LitB b) = b
eval (Arr l ixf) = listArray (zero,lm1) $
map (eval . ixf . value) [zero..lm1]
where lm1 = eval l Prelude.- succ zero
-- Fix me. I should probably separate this code with the examples
-- so that I don't need RebindableSyntax when defining this function
zero = lm1 Prelude.- lm1
eval (While c b i) = head $
dropWhile (eval . c . value) $
iterate (eval . b . value) $
eval i
eval (If c t e) = if eval c then eval t else eval e
eval (Pair a b) = (eval a, eval b)
eval (Fst p) = fst (eval p)
eval (Snd p) = snd (eval p)
eval (Prim1 _ f a) = f (eval a)
eval (Prim2 _ f a b) = f (eval a) (eval b)
eval (Value a) = a
value = Value
instance Show (FunC a) where
show (LitI i) = show i
show (LitB b) = show b
show (While c b i) = "while (s = " ++ show i ++ ";" ++
show (c (Variable "s")) ++ ") \n" ++
" s = " ++ show (b (Variable "s"))
show (If c t e) = "if " ++ show c ++
" then " ++ show t ++
" else " ++ show e
show (Pair a b) = "(" ++ show a ++ "," ++ show b ++ ")"
show (Fst p) = "fst " ++ show p
show (Snd p) = "snd " ++ show p
show (Prim1 f _ a) = f ++ " (" ++ show a ++ ")"
show (Prim2 f _ a b) = f ++ " (" ++ show a ++ ") (" ++ show b ++ ")"
show (Arr l ixf) = "{ " ++ show (ixf (Variable "i")) ++
" | i <- 0 .. " ++ show (l-1) ++ " }"
show (Undef) = "undefined"
show (Variable v) = v
instance (Syntactic a, Show b) => Show (a -> b) where
show f = "\\ a -> " ++ show (f (fromFunC (Variable "a")))
-- Nicer Interface
class Syntactic a where
type Internal a
toFunC :: a -> FunC (Internal a)
fromFunC :: FunC (Internal a) -> a
instance Syntactic (FunC a) where
type Internal (FunC a) = a
toFunC ast = ast
fromFunC ast = ast
true :: FunC Bool
true = LitB True
false :: FunC Bool
false = LitB False
undef :: Syntactic a => a
undef = fromFunC Undef
ifC :: Syntactic a => FunC Bool -> a -> a -> a
ifC c t e = fromFunC (If c (toFunC t) (toFunC e))
c ? (t,e) = ifC c t e
while :: Syntactic s => (s -> FunC Bool) -> (s -> s) -> s -> s
while c b i = fromFunC (While (c . fromFunC) (toFunC . b . fromFunC) (toFunC i))
instance Prelude.Eq (FunC Int) where
instance Num (FunC Int) where
(+) = Prim2 "(+)" (+)
(-) = Prim2 "(-)" (-)
(*) = Prim2 "(*)" (*)
negate = Prim1 "negate" negate
abs = Prim1 "abs" abs
signum = Prim1 "signum" signum
fromInteger = LitI . fromInteger
(==) :: FunC Int -> FunC Int -> FunC Bool
(==) = Prim2 "(==)" (Prelude.==)
-- Shallow Embeddings
-- Pairs
instance (Syntactic a, Syntactic b) => Syntactic (a,b) where
type Internal (a,b) = (Internal a, Internal b)
toFunC (a,b) = Pair (toFunC a) (toFunC b)
fromFunC p = (fromFunC (Fst p), fromFunC (Snd p))
pair :: (Syntactic a, Syntactic b) =>
a -> b -> (a,b)
pair a b = fromFunC (Pair (toFunC a) (toFunC b))
fstP :: (Syntactic a, Syntactic b) =>
(a,b) -> a
fstP (a,_) = a
sndP :: (Syntactic a, Syntactic b) =>
(a,b) -> b
sndP (_,b) = b
-- Option
data Option a = Option { isSome :: FunC Bool
, fromSome :: a
}
instance Syntactic a => Syntactic (Option a) where
type Internal (Option a) = (Bool,Internal a)
fromFunC m = Option (Fst m) (fromFunC (Snd m))
toFunC (Option b a) = Pair b (toFunC a)
some :: a -> Option a
some a = Option true a
none :: Syntactic a => Option a
none = Option false undef
option :: (Syntactic a, Syntactic b) =>
b -> (a -> b) -> Option a -> b
option noneCase someCase opt = ifC (isSome opt)
(someCase (fromSome opt))
noneCase
instance Functor Option where
fmap f (Option b a) = Option b (f a)
instance Monad Option where
return a = some a
opt >>= k = b { isSome = isSome opt ? (isSome b, false) }
where b = k (fromSome opt)
divO :: FunC Int -> FunC Int -> Option (FunC Int)
divO a b = (b == 0) ? (none, some (a `divP` b))
divP :: FunC Int -> FunC Int -> FunC Int
divP a b = Prim2 "div" div a b
-- Vectors
data Vector a where
Indexed :: FunC Int -> (FunC Int -> a) -> Vector a
instance Syntactic a => Syntactic (Vector a) where
type Internal (Vector a) = Array Int (Internal a)
toFunC (Indexed l ixf) = Arr l (toFunC . ixf)
fromFunC arr = Indexed (len arr) (\ix -> arr +!+ ix)
instance Syntactic a => Show (Vector a) where
show = show . toFunC
len :: FunC (Array Int a) -> FunC Int
len arr = Prim1 "length" (uncurry subtract . bounds) arr
lenV :: Vector a -> FunC Int
lenV (Indexed l _) = l
(+!+) :: Syntactic a => FunC (Array Int (Internal a)) -> FunC Int -> a
arr +!+ ix = fromFunC (Prim2 "index" (!) arr ix)
takeVec :: FunC Int -> Vector a -> Vector a
takeVec i (Indexed l ixf) = Indexed (minF i l) ixf
enumVec :: FunC Int -> FunC Int -> Vector (FunC Int)
enumVec f t = Indexed (t - f + 1) (\ix -> ix + f)
instance Functor Vector where
fmap f (Indexed l ixf) = Indexed l (f . ixf)
minF :: FunC Int -> FunC Int -> FunC Int
minF a b = Prim2 "min" Prelude.min a b
(>=) :: FunC Int -> FunC Int -> FunC Bool
a >= b = Prim2 "(>=)" (Prelude.>=) a b
-- Example programs
modulus :: FunC Int -> FunC Int -> FunC Int
modulus a b = while (>=b) (subtract b) a
modulusTest = modulus 17 2
vecTest n = fmap (+7) $ fmap (*3) $ enumVec 5 n
vecTestPrint = putStrLn $ show $ vecTest
squares :: FunC Int -> Vector (FunC Int)
squares n = fmap square $ enumVec 1 n
where square x = x * x
divTest :: FunC Int -> FunC Int -> FunC Int -> Option (FunC Int)
divTest a b c = do r1 <- divO a b
r2 <- divO a c
return (a+b)