## Getting started

Open a new file in `DrRacket`

and add the following definitions to the
beginning. This makes available some definitions from racket in
`plai-typed`

.

```
#lang plai-typed
(module tutorial6 typed/racket/base
(require racket/math)
(require (prefix-in plot: plot))
(provide plot sin cos pi)
(define (plot [fn : (Real -> Real) ] [from : Real] [to : Real])
(plot:plot
(plot:function fn from to)))
)
(require (typed-in 'tutorial6
[plot : ((number -> number) number number -> void)]
[pi : number]
[sin : (number -> number)]
[cos : (number -> number)]))
```

For the rest of the tutorial, add various definitions discussed to your file. Make a note of the types of the functions discussed.

## Derivatives and integrals

We can (crudely) approximate a derivative with the following higher order function.

```
(define dx 0.001)
;; compute the derivative of `f` at the given point `x`
(define (deriv f x)
(/ (- (f (+ x dx)) (f x)) dx))
```

Similarly, we can approximate the integral of a function at a point (more precisely from 0 to the point):

```
;; compute an integral of `f' at the given point `x'
(define (integrate f x)
(local
[(define (loop y acc)
(if (> y x)
(* acc dx)
(loop (+ y dx) (+ acc (f y)))))]
(loop 0 0)))
```

And say that we want to try out various functions given some `plot' function that draws graphs of numeric functions, for example:

```
(define -2pi (* -2 pi))
(define 2pi (* 2 pi))
(plot sin -2pi 2pi)
```

The problem is that `plot`

expects a single `(number -> number)`

function -- if we want to try it with a derivative, we can do this:

```
;; the derivative of sin
(define sin-deriv (lambda (x) (deriv sin x)))
(plot sin-deriv -2pi 2pi)
```

But this will get very tedious very fast -- it is much simpler to use an anonymous function:

```
(plot (lambda (x) (deriv sin x)) -2pi 2pi)
```

we can even verify that our derivative is correct by comparing a known
function to its derivative. Fill in the blank in the following with
the derivative of `sin`

```
(plot (lambda (x) (- (deriv sin x) )) -2pi 2pi)
```

But it's still not completely natural to do these things -- you need to explicitly combine functions, which is not too convenient. What can you observe about the numerical error here?

### Combinators

Instead of explicitely combining , we can write H.O. functions that will work with functional inputs and outputs. Such functions are called 'combinators. For example, we can write a function to subtract functions:

```
(define (fsub f g)
(lambda (x) (- (f x) (g x))))
```

Notice that the inferred type for fsub is a bit too general. Add type annotations to fix this.

We can similarly mamke a combinator to compute (indefinite) integrals.

```
(define (fderiv f)
(lambda (x) (deriv f x)))
```

Now we can try the same error calculation in a much easier way:

```
(plot (fsub (fderiv sin) cos) -2pi 2pi)
```

More than that -- our `fderiv`

could be created from `deriv`

automatically:

```
;; convert a double-argument function to a curried one
(define (currify f)
(lambda (x) (lambda (y) (f x y))))
;; compute the derivative function of `f'
(define fderiv2 (currify deriv))
```

Same principle with `fsub`

: we can write a function that converts a
binary arithmetical function into a function that operates on unary
numeric function. But to make things more readable we can define new
types for unary and binary numeric functions:

```
;; turns an arithmetic binary operator to a function operator
(define (binop->fbinop op)
(lambda (f g)
(lambda (x) (op (f x) (g x)))))
```

Use binop->fbinop to define a new version of fsub (e.g. calling it fsub2).

As a final exercise, define a combinator called "fintegrate" to make the following plot call work:

```
;; want to verify that `integrate' is the opposite of `deriv':
;; take a function, subtract it from its derivative's integral
(plot (fsub sin (fintegrate (fderiv2 sin))) 0 2pi)
```

This is one line if you use `currify`

.