Haskell notes

There aren't There are
Assignations Recursion
Loops Functions
Var declarations Computationally complete
Status Easy
Von Neuman Reliable
Efficency Elegant
Verifiable

Theorem

Any recursive algorythm can be transformed into an iterative one and vice versa. Corollary: We haven't loose calculation power.

Haskell

Currying

Maths Haskell
f(2, 3) f 2 3
f(a, b) ± c * d f a b ± c * d
g(a) + b g a + b
f(a + b, c) f (a + b) c
f(x, g(y)) f x (g y)

Hugs

To load a program with hugs use :l (or :load) program.hs

Redex: Reduction expression

It is better to evaluate from outside to inside

square::Int->Int
square x = x * x

>2 + square 3 -> 2 + (3 * 3) -> 2 + (9) -> 11
>square(square 3) -> (square 3)*(square 3) -> (3 * 3) * (square 3) ->
-> 9 * (square 3) -> 9 * (3 * 3) -> 9 * 9 -> 81

Haskell uses some kind of lazy evaluation with sharing, a graphs structure. I'll try to explain it here:

square 3 -> · * · -> 9, where · points to 3
square (square 3) -> · * · where · points to square 3 ->
  -> · * · where each · points to ~ * ~ where ~ points to 3 -> 
  -> · * · where · points to 9 -> 81

Comparisions

(==), (<), (>), (<=), (>=), (/=)

Types

Example: >True < 'a' returns Type Error

The command >:set +t returns the type used to have more info, like a debug.

Tuple

Mixed component where the type of each component can be different.

Lists

Must be of the same type, but there's no limit of elements. Lists doesn't have pointers.

The arrow (->)

It's used to construct types. Having t1, t2, ..., tn, tr can construct something like t1 -> t2 -> ... -> tn -> tr which means that it takes a type t1, type t2, ..., type tn, and returns a type tr.

Pattern adjustment

Haskell evaluates several functions in order and when it finds a rule that works correctly, returns that. Example:

f::Int -> Bool
f 1 = True
f 2 = False
f x = False
>f 1 -> True
>f 2 -> False
>f 3 -> False -- If we didn't put "f x = False" this will throw an error.

f:Int -> Bool
f x = True
f 2 = False
>f 2 -> True -- Because it evaluates first "f x" and it matches.

Recursive examples

More patterns

Definition of functions by cases

  sign::Int->Int
  sign x  | x > 0 = 1 -- These are called guards
          | x < 0 = -1
          | otherwise = 0
  abs::Int->Int
  abs x   | x >= 0 = x
          | otherwise = -x

Conditionals

  ifThenElse::Bool->Int->Int->Int
  ifThenElse True x _ = x
  ifThenElse False _ y = y

Case expressions

  sum::[Int]->Int
  sum xs = case xs of
            [] = 0
            (y:ys) -> y + sum ys

Error function

  head::[Int]->Int
  head [] = error 'list is empty'
  head (x:_) = x

Local definitions

For this example we'll solve the equation ax²+bx+c=0 with (-b±sqrt(d))/2a being d = b²-4ac

  roots::(Float, Float, Float) -> (Float, Float)
  roots (a, b, c)
    | d >= 0 = ((-b + sqrt d) / (2 * a), (-b - sqrt d) / (2 * a)
    | otherwise = error "..."
    where : d = b * b - 4 * a * c
  {-
    we could add also in where more local definitions like
    "rd = sqrt d" and "da = 2 * a" and replace them in the equation.
  -}

We could also create a type, for example:

  type Complex=(Float, Float)
  roots::(Float, Float, Float) -> (Complex, Complex)

Local declarations

Important! guards, let, where, of, do... must be correctly indented!!

Operators

  >1 + 2
  3
  >(+) 1 3
  4
  >mod 10 3
  1
  >10 `mod` 3
  1

List of infix operators

: ! # $ % & * + · / < = > ? @ \ ^ | - ~ && || /= //

Declaring operators

infix <priority [0..9]> <op-name>
infixr <priority> <op> -- from right
infixl <priority> <op> -- from left
--
infixr 9 ·
infixl 9 !!
infixr 8 ^, ^^, **
infixr 3 &&
infixl 2 ||
--
infixr 2 ||| --exclusive or
(|||)::Bool->Bool->Bool
True ||| True = False
False ||| False = False
_ ||| _ = True

Superior order

An argument is a function or returns a function

  twice::(Int -> Int) -> Int -> Int
  twice f x = f (f x)

  dev,inc::Int->Int
  inc x = x + 1
  dec x = x - 1

  twice inc 10 -> inc (inc 10) -> inc (10 + 1) -> inc 11 -> 11 + 1 -> 12

Examples

Anonymous Functions. Lambda-expression. λ

(λx -> x + 1)::Int->Int In Haskell, lambda is written with \ instead of λ.

  >\x -> x + 1
  << function >>::Int->Int
  >(\x -> x + 1) 3
  4

Some examples

Partial application

f::(t1->(t2->...->(tx->...->(tn->(tr)))))

f e1 e2... ek::tk+1 -> ... tn -> tr

Example:

  f::Int->Int->Int->Int
  f x y z = x * (2 * y + z)
  >f
  <<function>>::Int -> (Int -> (Int -> Int))
  >f 2
  <<function>>::Int -> (Int -> Int)
  >f 2 3
  <<function>>::Int -> Int
  >f 2 3 4 -- Total application
  20

Sections

Binary operators partially applied with recieve only an argument.