You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We'd also like to model one of the versions of the delta operator, finite difference, in our syntax tree. As the semantic value of our calculus language is the unary real function, the difference used for averages doesn't really fit in well, as it's a binary function (two arguments: $t_2$ and $t_1$). Instead, we'll use the version of delta used for instantants, as it only takes a single point in time as an argument (assuming $h$ is already given).
141
+
We'd also like to model one of the versions of the delta operator,
142
+
finite difference, in our syntax tree. As the semantic value of our
143
+
calculus language is the unary real function, the difference used for
144
+
averages doesn't really fit in well, as it's a binary function (two
145
+
arguments: $t_2$ and $t_1$). Instead, we'll use the version of delta
146
+
used for instants, as it only takes a single point in time as an
147
+
argument (assuming $h$ is already given).
142
148
143
149
The constructor in our syntax tree is therefore
144
150
@@ -185,8 +191,8 @@ Introducing *infinitesimals*! From the wikipedia entry on *Leibniz's notation*
Copy file name to clipboardExpand all lines: Physics/src/Calculus/FunExpr.lhs
+50-53Lines changed: 50 additions & 53 deletions
Original file line number
Diff line number
Diff line change
@@ -1,4 +1,4 @@
1
-
> moduleCalculus.FunExpr (FunExpr (..), RealNum) where
1
+
> moduleCalculus.FunExpr (FunExpr (..), RealNum, RealFunc) where
2
2
>
3
3
> importTest.QuickCheck
4
4
@@ -16,12 +16,12 @@ $$\frac{d f(x)}{dx} = f'(x)$$
16
16
17
17
Hmm, these examples left me more confused than before. The
18
18
differentiation function seems to take an expression as an argument,
19
-
and return the derived expression, with regards to a variable. But
20
-
what is an expression represented as a semantic value? It's not a
21
-
number yet, the variable in the body needs to be substituted first in
22
-
order for the expression to be computable. Is it some kind of function
23
-
then? Well, yes it is! If we reinterpret the differentiation
24
-
expressions above, it makes more sense.
19
+
and return the differentiated expression, with regards to a
20
+
variable. But what is an expression represented as a semantic value?
21
+
It's not a number yet, the variable in the body needs to be
22
+
substituted first in order for the expression to be computable. Is it
23
+
some kind of function then? Well, yes it is! If we reinterpret the
24
+
differentiation expressions above, it makes more sense.
25
25
26
26
$$\frac{d x^2}{dx} = 2x$$
27
27
@@ -40,15 +40,14 @@ $$D(square) = double$$.
40
40
So the type of unary real functions seems like a great fit for a
41
41
semantic value for calculus, and it is! Great! But... how do we
42
42
represent a real number in Haskell? There is no `Real` type to
43
-
use. Well, for simplicitys sake we can just say that a real number is
44
-
basically the same as a `Double`, and it is (basically). The problem
45
-
with `Double` is that it's of finite precision, so rounding errors may
46
-
occur. We'll have to keep that in mind when doing calculations!
43
+
use. Well, for the sake of simplicity we can just say that a real
44
+
number is basically the same as a `Double`, and really it is
45
+
(basically). The problem with `Double` is that it's of finite
46
+
precision, so rounding errors may occur. We'll have to keep that in
47
+
mind when doing calculations!
47
48
48
49
> typeRealNum=Double
49
-
>
50
-
>-- The type of the semantic value of calculus is the unary real function
51
-
>-- RealNum -> RealNum
50
+
> typeRealFunc=RealNum->RealNum
52
51
53
52
Now, to the syntax. We've concluded that real functions are really
54
53
what calculus is all about, so let's model them. We create a data type
@@ -59,36 +58,31 @@ language.
59
58
60
59
> dataFunExpr
61
60
62
-
First of all, there's the elementary functions. We can't have them
61
+
First of all, there are the elementary functions. We can't have them
63
62
all, that would get too repetitive to implement, but we'll put in all
64
63
the fun ones.
65
64
66
-
>=Exp
67
-
> | Log
68
-
> | Sin
69
-
> | Cos
70
-
> | Asin
71
-
> | Acos
65
+
>=Exp | Log | Sin | Cos | Asin | Acos
72
66
73
67
Then, there are the arithmetic operators. "But wait", you say, "Aren't
74
-
arithmetic operators used to combine expressions, not functions?". I
75
-
hear you, Billy, but we will do it anyways. We could make a `Lambda`
68
+
arithmetic operators used to combine expressions, not functions?". We
69
+
hear you friend, but we will do it anyways. We could make a `Lambda`
76
70
constructor for "VAR $\mapsto$ EXPR" expressions and define the
77
71
arithmetic operators for the expression type, but this would make
78
72
our language much more complicated! Instead, we'll restrain ourselves
79
73
to single variable expressions, which can be represented as
80
74
compositions of unary functions, and define the arithmeric operators
81
75
for the functions instead.
82
76
83
-
$$f \text{ OP } g = x \mapsto (f(x) \text{ OP } g(x))$$
77
+
$$f \text{ $OP_{r \to r}$ } g = x \mapsto (f(x) \text{ $OP_r$ } g(x))$$
84
78
85
79
> | FunExpr:+FunExpr
86
80
> | FunExpr:-FunExpr
87
81
> | FunExpr:*FunExpr
88
82
> | FunExpr:/FunExpr
89
83
> | FunExpr:^FunExpr
90
84
91
-
And then theres that single variable. As everything is a function
85
+
And then there's that single variable. As everything is a function
92
86
expression, the function that best represents "just a variable" would
93
87
be $x \mapsto x$, which is the same as the $id$ function.
94
88
@@ -98,23 +92,23 @@ In a similar vein, the constant function. $const(c) = x \mapsto c$
98
92
99
93
> | ConstRealNum
100
94
101
-
Then theres function composition. If you didn't already know it, it's
95
+
Then there's function composition. If you didn't already know it, it's
102
96
defined as
103
97
104
-
$$f . g = x \mapsto f(g(x))$$
98
+
$$f \circ g = x \mapsto f(g(x))$$
105
99
106
100
> | FunExpr:.FunExpr
107
101
108
-
Finally, the real heroes: The functions of difference, differentiation,
109
-
and integration! They will be well explored later. But for now, we
102
+
Finally, the real heroes: the functions of difference, differentiation,
103
+
and integration! They will be well explored later. But for now, we just
110
104
define the syntax for them as
111
105
112
106
> | DeltaRealNumFunExpr
113
107
> | DFunExpr
114
108
> | IFunExpr
115
109
116
110
Even more finally, we add a `deriving` modifier to automatically allow
117
-
for equality tests between `FunExpr`s.
111
+
for syntactic equality tests between `FunExpr`s.
118
112
119
113
>derivingEq
120
114
@@ -141,7 +135,7 @@ left-associative, and set the precedence.
141
135
>infixl7:/
142
136
>-- Higher precedence
143
137
>infixl8:^
144
-
>--Higherer precedence
138
+
>--Can't go higher than this precedence
145
139
>infixl9:.
146
140
147
141
@@ -155,7 +149,7 @@ for: `Show` and `Arbitrary`.
155
149
156
150
Try modifying `FunExpr` to derive `Show`, so that our expressions can be printed.
157
151
158
-
<derivingEq, Show
152
+
<deriving(Eq, Show)
159
153
160
154
Consider now how GHCi prints out a function expression we create
161
155
@@ -167,30 +161,33 @@ Consider now how GHCi prints out a function expression we create
167
161
168
162
Well that's borderline unreadable. Further, the grokability of a printed expression is very inversely proportional to the size/complexity of the expression, as I'm sure you can imagine.
169
163
170
-
So if the `Show` is bad, we'll just have to make our own `Show`!
171
-
172
-
> instanceShowFunExprwhere
173
-
>showExp="exp"
174
-
>showLog="log"
175
-
>showSin="sin"
176
-
>showCos="cos"
177
-
>showAsin="asin"
178
-
>showAcos="acos"
179
-
>show(f :+ g) ="("++show f ++" + "++show g ++")"
180
-
>show(f :- g) ="("++show f ++" - "++show g ++")"
181
-
>show(f :* g) ="("++show f ++" * "++show g ++")"
182
-
>show(f :/ g) ="("++show f ++" / "++show g ++")"
183
-
>show(f :^ g) ="("++show f ++"^"++show g ++")"
184
-
>showId="x"
185
-
>show (Const x) = showReal x
186
-
>show(f :. g) ="("++show f ++" . "++show g ++")"
187
-
>show(Delta h f) ="(delta_"++ showReal h ++""++show f ++")"
188
-
>show(D f) ="(D "++show f ++")"
189
-
>show(I f) ="(I "++show f ++")"
164
+
So if the derived `Show` is bad, we'll just have to make our own `Show`!
165
+
166
+
> showFe::FunExpr->String
167
+
>showFeExp="exp"
168
+
>showFeLog="log"
169
+
>showFeSin="sin"
170
+
>showFeCos="cos"
171
+
>showFeAsin="asin"
172
+
>showFeAcos="acos"
173
+
>showFe (f :+ g) ="("++showFe f ++" + "++showFe g ++")"
174
+
>showFe (f :- g) ="("++showFe f ++" - "++showFe g ++")"
175
+
>showFe (f :* g) ="("++showFe f ++" * "++showFe g ++")"
176
+
>showFe (f :/ g) ="("++showFe f ++" / "++showFe g ++")"
177
+
>showFe (f :^ g) ="("++showFe f ++"^"++showFe g ++")"
178
+
>showFe Id="id"
179
+
>showFe (Const x) = showReal x
180
+
>showFe (f :. g) ="("++showFe f ++" . "++showFe g ++")"
181
+
>showFe (Delta h f) ="(delta_"++ showReal h ++""++showFe f ++")"
182
+
>showFe (D f) ="(D "++showFe f ++")"
183
+
>showFe (I f) ="(I "++showFe f ++")"
190
184
>
191
185
> showReal x =if isInt x thenshow (round x) elseshow x
192
186
>where isInt x = x ==fromInteger (round x)
193
187
188
+
> instanceShowFunExprwhere
189
+
>show= showFe
190
+
194
191
Not much to explain here. It's just one way to print our syntax tree
195
192
in a more readable way. What's interesting is how we can now print our
196
193
expressions in a much more human friendly way!
@@ -200,7 +197,7 @@ expressions in a much more human friendly way!
200
197
201
198
Still a bit noisy with all the parentheses, but much better!
202
199
203
-
Another class we need to instance for our `FunExpr` is
200
+
Another class we can instance for our `FunExpr` is
204
201
`Arbitrary`. This class is associated with the testing library
205
202
*QuickCheck*, and describes how to generate arbitrary values of a type
206
203
for use when testing logical properties with `quickCheck`. For
0 commit comments