Gofer Functions
NAME FP ... = EXP
where NAME is the name of the function, FP ... is a list of 0 or
more formal parameters, and EXP is a parameterized expression.
A constant definition is just a parameterless function:
> zero = 0
> one = 1
> two = 2
Here are some more examples of simple definitions:
> square x = x * x
> rel_prime x y = gcd x y == 1
> divides n m = rem m n == 0
> add_mod_n x y n = mod (x + y) n
> dist x y = abs (x - y)
> sos x y = x^2 + y^2
> always_0 x = 0
Here is a list of some primitive Gofer functions:
div (aka /), rem, mod, odd, even, gcd, lcm, abs, signum,
max, min, ^, ord, chr, &&, ||, not, <, <=, ==, >, >=, +, *
NAME FP ...
= EXP, if GUARD
= EXP, GUARD
etc.
= EXP, otherwise
where GUARD is any Boolean-valued expression
Note: EXP, if GUARD is called a guarded expression. All guarded expressions must be to the right of all = signs.
Examples:
> max_sos x y z
> = sos x y, if z < min x y
> = sos x z, if y < min x z
> = sos y z, otherwise
> xor x y
> = x || y, if (x /= y) -- not equal
> = False, otherwise
We can use conditionals to define recursive functions:
> fact n
> = 1, if n == 0
> = n * fact (n - 1), otherwise
Problem: Define
choose m n = # of ways to choose m objects from n objects
> NAME FP ...
> = RHS
> where
> DEF ...
Here are some examples
> tax income
> = rate * income
> where
> rate = 0.3
> close x y
> = dist x y < delta
> where
> delta = 1e-20
> dist x y = abs (x - y)
> area r
> = pi * r * r
> where
> pi = 3.1416
Since the "w" in "where" is one column to the left of the "=",
Gofer will assume this is the beginning of the next definition,
instead of a where block associated with the previous definition!
? :t 42
Int
? :t True
Bool
? :t cube
Float->Float
? :t always_o
a->Int
Notice that the input type of always_0 is a variable, a. This
signals that the input to always_0 can belong to any type.
a->Int is called a polytype, and always_0 is a polymorphic function.
? always_0 1/0
0
This is possible because Gofer uses lazy or delayed evaluation.
> compose f g
> = h
> where
> h x = f g x
Note, compose is a built-in operator in Gofer:
> compose f g = f . g
? :t sos
Float->Float->Float
This says sos expects a single Float as input, and returns
a function of type Float->Float as output. For example,
if we define:
> sos2 = sos 2
Then
? :t sos2
Float->Float
? sos2 3
16
? sos2 2
8
sos2 is a function which expects a single input, y, and
returns 4 + y^2 as output.