---Haskell is a strongly typed
---lazy, pure, higher-order, polymorphic functional language


--First simple expressions +, -, ++ (strings and lists), and show
---length, type of length  let expressions
---including let expressions that define functions. Also show types. 

---show types if invidiual elements: numbers, characters, strings. 
---Show types of lists of integers, characters etc. Discuss 
   how lists of integers can only be appended to lists of integers. 
--show types of sqrt, head, tail. 
---show types of integer operatios, +, - etc
---show types of polymoprhic types, "head",tail, ++, take, etc. 


---Then we get into higher-order features. 



-- feature currying, show +1, ++"foo", etc.

---Next feature, higher order functions. 
--discuss their types. 
--first example is double. 

double f x = f (f x)

double2 f = f . f

--Show double (+1), double (+2), etc. 

--Point out that this type of currying cannot be done with C function 
--pointers. (It's called a closure). 

--- Now, show that it's polymprhicalso double ("hello "++)

---Now, also show that it is higher-order polymorphic, double double

--Then Map. 

--Talk about the type of maps. 

mymap f [] = []
mymap f (h:r)  = (f h):(mymap f r)

incr = mymap (+1) 

incrs = mymap ("hello "++)


---Then Folds. 

myfoldr            :: (a -> b -> b) -> b -> [a] -> b
myfoldr f z []      = z
myfoldr f z (x:xs)  = f x (myfoldr f z xs)


myfoldl            :: (a -> b -> a) -> a -> [b] -> a
myfoldl f z []      = z
myfoldl f z (x:xs)  = myfoldl f (f z x) xs

---Then laziness
---even C is lazy, in the short-circuit boolean. 
---Illustrate lazienss with things like take 3 [1,2,3,5/0]
--and drop 2 [0/0, 1/0, 3 , 4]


myrepeat item = item : (myrepeat item)

nrepeat 0 item  = []
nrepeat n item  = item : (nrepeat (n-1) item)

myiterate f x =  x : myiterate f (f x)


firstn 0 l  = []
firstn n [] = []
firstn n (h:t)  = [h] ++ (firstn  (n-1) t)


fib 0     = 0                               -- using pattern matching:
fib 1     = 1                               -- base cases...
fib (n+2) = fib n + fib (n+1)               -- recursive case


---First explain zipWith

fastFib n = fibs !! n                       -- using an infinite stream
            where fibs = 0 : 1 : zipWith (+) fibs (tail fibs)



--THen explain iterate:

-- take 5 (iterate (+1) 1)
--take 5 (iterate ("hello "++)  "Matt")

--Then explain Sieve:


primes      :: Integral a => [a]
primes       = map head (iterate sieve [2..])
sieve (p:xs) = [ x | x<-xs, x `rem` p /= 0 ]


iseven x = ((x `rem` 2) == 0)


-----------next, talk about constructors, using Tree example
----illustrate how flatten works on trees. 


