-
Notifications
You must be signed in to change notification settings - Fork 6
/
Expressions.hs
151 lines (100 loc) · 3.11 KB
/
Expressions.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
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE PartialTypeSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE GADTs #-}
module Expressions where
import ALaCarte hiding (inject)
-- extra functor coproduct stuff
{-| Utility function to case on a functor sum, without exposing the internal
representation of sums. -}
caseF :: (f a -> b) -> (g a -> b) -> (f :+: g) a -> b
{-# INLINE caseF #-}
caseF f g x = case x of
Inl x -> f x
Inr x -> g x
projL :: (f :+: g) a -> Maybe (f a)
projL s = case s of
Inl fa -> Just fa
Inr _ -> Nothing
projR :: (f :+: g) a -> Maybe (g a)
projR s = case s of
Inl _ -> Nothing
Inr ga -> Just ga
-- Fix
newtype Fix f = Fix { unfix :: f (Fix f) }
deriving instance (Show (f (Fix f))) => Show (Fix f)
deriving instance (Eq (f (Fix f))) => Eq (Fix f)
inject :: (f :<: g) => f (Fix g) -> Fix g
inject = undefined
project :: (f :<: g) => Fix g -> Maybe (f (Fix g))
project = undefined
------- Simple language of arithmetic expressions
data Val a = Val Int deriving (Functor, Show, Eq)
data Add a = Add a a deriving (Functor, Show, Eq)
data Mul a = Mul a a deriving (Functor, Show, Eq)
type IntExpr = Fix Val
type AddExpr = Fix Add
intExpr :: IntExpr
intExpr = Fix (Val 3)
addExpr :: AddExpr
addExpr = Fix (Add addExpr addExpr)
-- add some smart constructors
val :: (Val :<: f) => Int -> Fix f
val = undefined
(|+|) :: (Add :<: f) => Fix f -> Fix f -> Fix f
x |+| y = undefined
(|*|) :: (Mul :<: f) => Fix f -> Fix f -> Fix f
x |*| y = undefined
fold :: Functor f => (f a -> a) -> Fix f -> a
fold f (Fix t) = undefined
---------
addExpr2 :: Fix (Add :+: Val)
addExpr2 = val 33 |+| val 9
----- evaluating
-----
----- an "algebra" for a functor f
----- is just a function f a -> a
-----
class Functor f => Alg f a where
ev :: f a -> a
instance Alg Val Int where
ev (Val v) = v
instance Alg Add Int where
ev (Add x y) = undefined
instance Alg Mul Int where
ev (Mul x y) = undefined
instance (Alg f x, Alg g x) => Alg (f :+:g) x where
ev = undefined
class Functor f => Eval f where
evalAlg :: f Int -> Int
instance Eval Val where
evalAlg (Val v) = undefined
instance Eval Add where
evalAlg (Add x y) = undefined
instance Eval Mul where
evalAlg (Mul x y) = undefined
instance (Eval f, Eval g) => Eval (f :+: g) where
evalAlg = undefined
eval :: Eval f => Fix f -> Int
eval = undefined
mulExpr :: Fix (Val :+: Mul)
mulExpr = val 42 |*| val 3
mulExpr_eval :: Int
mulExpr_eval = eval mulExpr
---- add a "pretty print" operation along the lines of eval
class Functor f => Print f where
--- implement
printExpr :: Print f => Fix f -> String
printExpr = undefined
-- optional:
-- how would you apply the algebraic transformation
-- x(a + b) = xa + xb
-- to expressions containing values, multiplications and additions?