Skip to content

Commit 24dae5e

Browse files
author
Oskar Lundström
committed
2 parents 39ad02f + baa36b3 commit 24dae5e

File tree

9 files changed

+141
-111
lines changed

9 files changed

+141
-111
lines changed

Book/style.css

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ div#toc ol > li > ul {
8686
border-radius: 5px;
8787
}
8888

89+
.center-img {
90+
display: block;
91+
border: 3px solid #F0F0F0;
92+
border-radius: 5px;
93+
}
94+
8995
.float-img-left, .float-img-right {
9096
width: 35%;
9197
}

Physics/src/Calculus/DifferentialCalc.lhs

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ average and instantaneous.
2626
Quotients of differences of functions of the same time describe the
2727
average rate of change over the time period. For example, an average
2828
velocity can be described as the difference quotient of difference in
29-
position divided by difference in time.
29+
position and difference in time.
3030

3131
$$v_{avg} = \frac{p_2 - p_1}{t_2 - t_1}$$ where $p_n$ is the position
3232
at time $t_n$.
@@ -43,7 +43,7 @@ $$ \Delta x = x_2 - x_1 $$
4343

4444
Ok, so it's a difference. But what does $x_2$ and $x_1$ mean, and what do they come from?
4545
$x_2$ and $x_1$ are not explicitly bound anywhere,
46-
but seems reasonable to assume that $x_i \in x$ or equivalently, that $x$
46+
but it seems reasonable to assume that $x_i \in \mathbb{R}$ or equivalently, that $x$
4747
is a function with a subscript index as an argument, that returns a $\mathbb{R}$.
4848

4949
Further, the indices $1,2$ should not be thought of as specific constants,
@@ -73,7 +73,7 @@ calculus we mainly use differences to express two things, as mentioned
7373
previously. Average rate of change and instantaneous rate of change.
7474

7575
Average rate of change is best described as the difference quotient of
76-
the difference in y-axis value over an interval of x, divided by the
76+
the difference in y-axis value over an interval of x, and the
7777
difference in x-axis value over the same interval.
7878

7979
$$\frac{y(x_b) - y(x_a)}{x_b - x_a}$$.
@@ -138,7 +138,13 @@ which can be used as
138138
< ghci> carSpeedAtPointsInTime
139139
< [1.9999999999833333,1.5402980985023251,0.5838486169602084,1.0006797790330592e-2]
140140

141-
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).
142148

143149
The constructor in our syntax tree is therefore
144150

@@ -185,8 +191,8 @@ Introducing *infinitesimals*! From the wikipedia entry on *Leibniz's notation*
185191
![](shrinking.png "Real smol boi"){.float-img-right}
186192

187193
So there's a special syntax for differences where the step $h$ is
188-
infinitely small, and it's called Leibniz's notation. We interpret the
189-
above quote in mathematical terms:
194+
infinitely small, and it's called Leibniz's notation. We could naively
195+
interpret the above quote in mathematical terms as
190196

191197
$$dx = lim_{\Delta x \to 0} \Delta x$$
192198

@@ -195,14 +201,19 @@ such that
195201
$$\forall y(x). D(y) = \frac{dy}{dx} = \frac{lim_{\Delta y \to 0} \Delta y}
196202
{lim_{\Delta x \to 0} \Delta x}$$
197203

198-
where $D$ is the function of differentiation.
204+
where $D$ is the function of differentiation. However, this doesn't
205+
quite make sense as $lim_{x \to 0} x = 0$ and we'd be dividing by
206+
0. The wording here is important: infinitesimals aren't $0$, but
207+
*infinitely* small! The result is that we can't define infinitesimals
208+
in terms of limits, but have to treat them as an orthogonal concept.
199209

200-
This definition of derivatives is very appealing, as it suggests a
201-
very simple and intuitive transition from finite differences to
202-
infinitesimal differentials. Also, it suggests the possibility of
203-
manipulating the infinitesimals of the derivative algebraically, which
204-
might be very useful. However, this concept is generally considered
205-
too imprecise to be used as the foundation of calculus.
210+
Except for this minor road bump, this definition of derivatives is
211+
very appealing, as it suggests a very simple and intuitive transition
212+
from finite differences to infinitesimal differentials. Also, it
213+
suggests the possibility of manipulating the infinitesimals of the
214+
derivative algebraically, which might be very useful. However, this
215+
concept is generally considered too imprecise to be used as the
216+
foundation of calculus.
206217

207218
A later section on the same wikipedia entry elaborates a bit:
208219

@@ -216,17 +227,17 @@ A later section on the same wikipedia entry elaborates a bit:
216227
> notations.
217228

218229
What is then the "right" way to do derivatives? As luck would have it,
219-
not much differently than Leibniz's suggested! The intuitive idea can
220-
be turned into a precise definition by defining the derivative to be
221-
the limit of difference quotients of real numbers. Again, from
222-
wikipedia - Leibniz's notation:
230+
not much differently than Leibniz's suggested and how we interpreted
231+
it above! The intuitive idea can be turned into a precise definition
232+
by defining the derivative to be the limit of difference quotients of
233+
real numbers. Again, from wikipedia - Leibniz's notation:
223234

224235
> In its modern interpretation, the expression dy/dx should not be read
225236
> as the division of two quantities dx and dy (as Leibniz had envisioned
226237
> it); rather, the whole expression should be seen as a single symbol
227238
> that is shorthand for
228239
>
229-
> $$D(x) = lim_{\Delta x \to 0} \frac{\Delta y}{\Delta x}$$
240+
> $$D(y) = lim_{\Delta x \to 0} \frac{\Delta y}{\Delta x}$$
230241

231242
which, when $y$ is a function of $x$, and $x$ is the $id$ function for real numbers (which it is in the case of time), is:
232243

@@ -238,7 +249,7 @@ D(y) &= lim_{\Delta x \to 0} \frac{\Delta y}{\Delta x} \\
238249
&= a \mapsto lim_{h \to 0} \frac{y(a + h) - y(a)}{h}
239250
\end{align*}
240251

241-
There, the definition of derivatives! Not to complicated, was it? We
252+
There, the definition of derivatives! Not too complicated, was it? We
242253
can write a simple numerically approximative according to the
243254
definition like
244255

@@ -247,10 +258,11 @@ definition like
247258
Only when $h$ is infinitely small is `deriveApprox` fully
248259
accurate. However, as we can't really represent an infinitely small
249260
number in finite memory, the result will only be approximative, and
250-
the approximation will get better as $h$ gets smaller. For example,
251-
let's calculate the slope of $f(x)=x^2$ at $f(3)$. As the slope of
252-
this parabola is calculated as $k = 2x$, we expect the result of
253-
`deriveApprox` to approach $k = 2x = 2*3 = 6$ as $h$ gets smaller
261+
the approximation will (in most cases) get better as $h$ gets
262+
smaller. For example, let's calculate the slope of $f(x)=x^2$ at
263+
$x=3$. As the slope of this parabola is calculated as $k = 2x$, we
264+
expect the result of `deriveApprox` to approach $k = 2x = 2*3 = 6$ as
265+
$h$ gets smaller
254266

255267
< ghci> deriveApprox (\x -> x^2) 5 3
256268
< 11
@@ -270,7 +282,7 @@ approximations!
270282

271283
We define a function to symbolically derive a function
272284
expression. `derive` takes a function expression, and returns the
273-
derived function expression.
285+
differentiated function expression.
274286

275287
> derive :: FunExpr -> FunExpr
276288

@@ -491,6 +503,7 @@ Intuitively, the identity function is the identity element for function composit
491503
> (f', g') -> f' :. g'
492504

493505
> simplify (Delta h f) = Delta h (simplify f)
506+
> simplify (D (I f')) = simplify f'
494507
> simplify (D f) = D (simplify f)
495508
> simplify (I f) = I (simplify f)
496509
> simplify f = f

Physics/src/Calculus/FunExpr.lhs

Lines changed: 50 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
> module Calculus.FunExpr (FunExpr (..), RealNum) where
1+
> module Calculus.FunExpr (FunExpr (..), RealNum, RealFunc) where
22
>
33
> import Test.QuickCheck
44

@@ -16,12 +16,12 @@ $$\frac{d f(x)}{dx} = f'(x)$$
1616

1717
Hmm, these examples left me more confused than before. The
1818
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.
2525

2626
$$\frac{d x^2}{dx} = 2x$$
2727

@@ -40,15 +40,14 @@ $$D(square) = double$$.
4040
So the type of unary real functions seems like a great fit for a
4141
semantic value for calculus, and it is! Great! But... how do we
4242
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!
4748

4849
> type RealNum = Double
49-
>
50-
> -- The type of the semantic value of calculus is the unary real function
51-
> -- RealNum -> RealNum
50+
> type RealFunc = RealNum -> RealNum
5251

5352
Now, to the syntax. We've concluded that real functions are really
5453
what calculus is all about, so let's model them. We create a data type
@@ -59,36 +58,31 @@ language.
5958

6059
> data FunExpr
6160

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
6362
all, that would get too repetitive to implement, but we'll put in all
6463
the fun ones.
6564

66-
> = Exp
67-
> | Log
68-
> | Sin
69-
> | Cos
70-
> | Asin
71-
> | Acos
65+
> = Exp | Log | Sin | Cos | Asin | Acos
7266

7367
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`
7670
constructor for "VAR $\mapsto$ EXPR" expressions and define the
7771
arithmetic operators for the expression type, but this would make
7872
our language much more complicated! Instead, we'll restrain ourselves
7973
to single variable expressions, which can be represented as
8074
compositions of unary functions, and define the arithmeric operators
8175
for the functions instead.
8276

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))$$
8478

8579
> | FunExpr :+ FunExpr
8680
> | FunExpr :- FunExpr
8781
> | FunExpr :* FunExpr
8882
> | FunExpr :/ FunExpr
8983
> | FunExpr :^ FunExpr
9084

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
9286
expression, the function that best represents "just a variable" would
9387
be $x \mapsto x$, which is the same as the $id$ function.
9488

@@ -98,23 +92,23 @@ In a similar vein, the constant function. $const(c) = x \mapsto c$
9892

9993
> | Const RealNum
10094

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
10296
defined as
10397

104-
$$f . g = x \mapsto f(g(x))$$
98+
$$f \circ g = x \mapsto f(g(x))$$
10599

106100
> | FunExpr :. FunExpr
107101

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
110104
define the syntax for them as
111105

112106
> | Delta RealNum FunExpr
113107
> | D FunExpr
114108
> | I FunExpr
115109

116110
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.
118112

119113
> deriving Eq
120114

@@ -141,7 +135,7 @@ left-associative, and set the precedence.
141135
> infixl 7 :/
142136
> -- Higher precedence
143137
> infixl 8 :^
144-
> -- Higherer precedence
138+
> -- Can't go higher than this precedence
145139
> infixl 9 :.
146140

147141

@@ -155,7 +149,7 @@ for: `Show` and `Arbitrary`.
155149

156150
Try modifying `FunExpr` to derive `Show`, so that our expressions can be printed.
157151

158-
< deriving Eq, Show
152+
< deriving (Eq, Show)
159153

160154
Consider now how GHCi prints out a function expression we create
161155

@@ -167,30 +161,33 @@ Consider now how GHCi prints out a function expression we create
167161

168162
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.
169163

170-
So if the `Show` is bad, we'll just have to make our own `Show`!
171-
172-
> instance Show FunExpr where
173-
> show Exp = "exp"
174-
> show Log = "log"
175-
> show Sin = "sin"
176-
> show Cos = "cos"
177-
> show Asin = "asin"
178-
> show Acos = "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-
> show Id = "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+
> showFe Exp = "exp"
168+
> showFe Log = "log"
169+
> showFe Sin = "sin"
170+
> showFe Cos = "cos"
171+
> showFe Asin = "asin"
172+
> showFe Acos = "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 ++ ")"
190184
>
191185
> showReal x = if isInt x then show (round x) else show x
192186
> where isInt x = x == fromInteger (round x)
193187

188+
> instance Show FunExpr where
189+
> show = showFe
190+
194191
Not much to explain here. It's just one way to print our syntax tree
195192
in a more readable way. What's interesting is how we can now print our
196193
expressions in a much more human friendly way!
@@ -200,7 +197,7 @@ expressions in a much more human friendly way!
200197

201198
Still a bit noisy with all the parentheses, but much better!
202199

203-
Another class we need to instance for our `FunExpr` is
200+
Another class we can instance for our `FunExpr` is
204201
`Arbitrary`. This class is associated with the testing library
205202
*QuickCheck*, and describes how to generate arbitrary values of a type
206203
for use when testing logical properties with `quickCheck`. For

0 commit comments

Comments
 (0)