Thursday, January 9, 2014

HASKELL INVERSE FUNCTIONS

HASKELL INVERSE FUNCTIONS

REVISED: Thursday, February 8, 2024




Haskell Inverse Functions.

I. FUNCTION

A function is a relation between sets where for each input there is exactly one output. We call the set a function is mapping from the domain or source the input; and we call the set a function is mapping to the range or codomain the output.

Let f be a continuous real injective and surjective function defined on a closed interval [(x1,y1),(x2,y2)].

Using Haskell:

f x = y

An injective function is one such that no two elements in the domain map to the same value in the codomain or range.

A one-to-one function is one such that for every value in the codomain or range there is exactly one value in the domain.

A surjective function is one such that for each element in the codomain or range there is at least one element in the domain that maps to it.

A bijective function is both injective and surjective.

In order for a function to have an inverse function it must be bijective and one-to-one.

A. FUNCTION INVERSE

A plot gives y as a function of x if every vertical line crosses the plot at most once, this is commonly known as the vertical line test. A function is one-to-one if every horizontal line crosses the plot at most once, which is commonly known as the horizontal line test. We can only find an inverse to a function when it is one-to-one otherwise we must restrict the domain.

If a function f maps every input to exactly one output an inverse of that function maps every output to exactly one input. The inverse of f is well-defined if and only if f is bijective and one-to-one.

A multiplicative inverse or reciprocal for a number x denoted by 1/x or x-1 is a number which when multiplied by x yields the multiplicative identity, 1.

The derivative of a function f(x) at x is the slope of the tangent line at x.

Using Haskell to find the slope of a line.

"Copy Paste" the following module into your text editor and "File, Save As" Slopes.hs to your working directory:

module Slopes where

slopew :: Fractional a => (a, a) -> (a, a) -> a
slopew (x1,y1) (x2,y2) = dy/dx
                                          where dy = y2 - y1
                                                      dx = x2 - x1

slopel :: Fractional a => (a, a) -> (a, a) -> a
slopel (x1,y1) (x2,y2) = let dy = y2 - y1
                                              dx = x2 - x1
                                          in dy/dx

GHCi, version 9.8.1: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude>

Load the module Slopes into GHCi as follows:

Prelude>  :load Slopes.hs
[1 of 1] Compiling Main             ( Slopes.hs, interpreted )
Ok, modules loaded: Main.
Prelude>

Call the function slopew as follows:

Prelude>  slopew (1,1) (2,2)
1.0
it :: Fractional a => a
Prelude>

Call the function slopel as follows:

Prelude>   slopel (1,1) (2,2)
1.0
it :: Fractional a => a
Prelude>  

The range of the function f is the interval [(x1,y1),(x2,y2)], or [(x2,y2),(x1,y1)] if (x2,y2) < (x1,y1).

The function which maps the range or codomain y to the domain or source x is called the inverse of the function f.

For example, suppose you are filling the gas tank of your car and there are 4 gallons of gas in your tank when you start. The volume of gas in gallons after t seconds of filling your gas tank at the rate of 2 gallons per second is given by volume as a function of time v(t):

v(t) = 2t + 4
v(t) = 2(t + 2)
v = 2(t + 2)

Using Haskell, volume as a function f time v(t), in this case is:

v :: Num a => a -> a
v t = 2 * ( t + 2 )

GHCi, version 9.8.1: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude>

Prelude>  let v t = 2 * ( t + 2 )
v :: Num a => a -> a
Prelude>

Prelude>  v 0     -- Time is zero when you start pumping the gas.
4                          --  At time zero you start with 4 gallons of gas in your tank.
it :: Num a => a
Prelude>  

What is the inverse of the function v(t); and what does the inverse of the function v(t) tell us? While v(t) tells us how many total gallons of gas are in the tank after a period of time in seconds the inverse of v(t) tells us how much time in seconds must be spent to fill our tank with a given total volume of gas in gallons.

To compute the inverse of volume as a function of time v(t) first set v = v(t) and then compute time as a function of volume t(v) as follows:

v(t) = 2(t + 2)
v = 2(t + 2)

Solving for t:

v /2 = t + 2
v /2 - 2 = t
t = v /2 - 2
t = v/2 - 4/2
t = 1/2(v - 4)

This is a function that maps volume in gallons to time in seconds:

t(v) = 1/2(v – 4)
t = 1/2(v – 4)

Using Haskell time as a function of volume t(v) is:

t :: Fractional a => a -> a
t v = 1/2 * (v – 4)

GHCi, version 9.8.1: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude>

Prelude>  let t v = 1/2 * (v - 4)
t :: Fractional a => a -> a
Prelude>

Prelude>  t 4   -- You start with 4 gallons of gas in your tank.
0.0                    -- You start at time zero.
it :: Fractional a => a
Prelude>

Therefore, as shown in Haskell the inverse of volume as a function of time v(t):

v :: Num a => a -> a
v t = 2 * ( t + 2 )

is time as a function of volume t(v):

t :: Fractional a => a -> a
t v = 1/2 * (v – 4)

III. INVERSE FUNCTION THEOREM

If f(x) is a differentiable function, and f'(x) is continuous, and f'(a) /= 0, then

(a) f-1(y) is defined for y near f(a),

(b) f-1(y) is differentiable near f(a),

(c) d/dy f-1(y) is continuous near f(a), and

(d) d/dy f-1f(y) = 1/(f'(f-1(y))).

IV. CONCLUSION

In this tutorial you have been introduced to Haskell inverse functions.

V. REFERENCES

Bird, R. (2015). Thinking Functionally with Haskell. Cambridge, England: Cambridge University Press.

Davie, A. (1992). Introduction to Functional Programming Systems Using Haskell. Cambridge, England: Cambridge University Press.

Goerzen, J. & O'Sullivan, B. &  Stewart, D. (2008). Real World Haskell. Sebastopol, CA: O'Reilly Media, Inc.

Hutton, G. (2007). Programming in Haskell. New York: Cambridge University Press.

Lipovača, M. (2011). Learn You a Haskell for Great Good!: A Beginner's Guide. San Francisco, CA: No Starch Press, Inc.

Thompson, S. (2011). The Craft of Functional Programming. Edinburgh Gate, Harlow, England: Pearson Education Limited.