content: --EDAN40 tenta 16.12.2013
  
  -- QUESTION 1
  -- write scanr, scanl and reverse
  scanr :: (a -> b -> b) -> b -> [a] -> [b]
  
  scanrR f z []      = [z]
  scanrR f z (x:xs)  = (:) (f x (head prev)) prev
                           where prev = scanrR f z xs
  
  scanrF f z l = foldr ff [z] l
                 where ff x xs = (f x (head xs)):xs
  
  scanl :: (a -> b -> a) -> a -> [b] -> [a]
  
  scanlR f z []     = [z]
  scanlR f z (x:xs) = z : scanlR f (f z x) xs
  
  scanlF f z l = foldl ff [z] l
                 where ff xs x = xs ++ (f (last xs) x):[]
  
  reverse :: [a] -> [a]
  reverse = foldl (flip (:)) []
  
  -- QUESTION 2
  -- subclass
  
  -- A method of introducing typeclasses with inherited constraints
  -- A subclass B of a class A must fullfill all the constraints posed on A, 
  -- together with possibly some additional ones, specific to B 
  
  -- notation:
  class A b where
    f1 :: b -> Int
  class A b => B b where
    f2 :: b -> b -> Bool
  
  -- in such case all instances of B will have both f1 and f2 defined
  
  -- QUESTION 3
  -- Church numerals
  -- 2 + 2 = 4
  
  -- twoC `plusC` twoC = fourC
  -- we have to remember about the extra parameter to Church numerals
  -- === stands for "is equivalent to"
  
  -- twoC `plusC` twoC f ===
  -- plusC twoC twoC f ===
  -- (twoC f).(twoC f) ===
  -- (f.f).(twoC f) ===
  -- f . (f . (twoC f)) ===
  -- f . (succC twoC f) ===
  -- f . (threeC f) ===
  -- succC threeC f ===
  -- fourC f
  
  
  -- QUESTION 4
  
  f :: (Monad m, Num b) => m b -> m b -> m b
  
  -- f [1,2,3] [2,4,8] = [2,4,8,4,8,16,6,12,24]
  -- f (Just 5) Nothing = Nothing
  -- yes, fmap (+2) (Just 5) is correct (and equal Just 7 BTW)
  -- return 5 :: (Monad m, Num a) => m a
  
  
  -- QUESTION 5
  -- seq, pseq, par, force
  
  seq, pseq, par :: a -> b -> b
  force :: xs -> xs
  
  -- seq: suggests evaluation of its first arg (up to WHNF), returns the second
  -- pseq: forces evaluation of the first arg first, then returns the second
  -- par: like seq, but evaluation of the first arg may be done in parallel with returning the second
  -- force: evaluates the spine of a list (up to WHNF)
  
  -- parSort2
  -- just enables parallel evaluation up to WHNF, no real effect (due to WHNF and laziness)
  
  -- parSort3
  -- slightly better attempt (let's force evaluation of lesser BEFORE the concatenation) but, 
  -- likewise, no real effect (laziness, WHNF)
  
  -- parSort4
  -- by enforcing the complete list evaluation (on top level at least) allows parallelism to improve the efficiency
  
  
  
  -- QUESTION 6
  
  -- type classes
  
  -- a:
  -- m1 and m2 contain different number of music objects, 
  -- thus line m1 and line m2 compose in parallel different number of music objects
  -- (even though the side effect (= the music itself) is the same!)
  -- line m1 = (Note (C,5) dur [] :+: Note (D,5) dur []) :+: (Note (E,5) dur [] :+: Rest (0 % 1))
  -- line m2 = Note (C,5) dur [] :+: (Note (D,5) dur [] :+: (Note (E,5) dur [] :+: Rest (0 % 1)))
  -- then
  -- lineToList (line m1) contains 2 elements
  -- lineToList (line m2) contains 3 elements
  
  -- b:
  -- a possible (incomplete, but sufficient for the task) solution
  line2 [] = (Rest 0)
  line2 ((Note x y z) : ms) = (Note x y z) :+: (line2 ms)
  line2 ((m1 :+: m2) : ms) = line2 (m1 : (m2 : ms))
  
  -- c:
  -- a possible (incomplete, but sufficient for the task) solution
  lineToList2 (Rest 0) = []
  lineToList2 (Note x y z) = [(Note x y z)]
  lineToList2 (Note x y z :+: ms) = (Note x y z): lineToList2 ms
  lineToList2 (m :+: ms) = lineToList2 m ++ lineToList2 ms
  
  -- Note: patterns may need to be modified to obey the current constraints of the language
  