data N = N L
data L = L1 B | L2 L B
data B = O | I

be :: B -> (Int -> a) -> a
be O c = c 0
be I c = c 1

le :: L -> Int -> (Int -> a) -> a
le (L1 b)   p0 c = be b (\v1 -> c (p0*v1))
le (L2 l b) p0 c = le l (2*p0) (\v1 -> be b (\v2 -> c (v1+p0*v2)))

ne :: N -> (Int -> a) -> a
ne (N l) = le l 1

test = ne (N (L2 (L2 (L2 (L1 I) O) I) I)) id == 11


quickSort :: Ord a => [a] -> [a]
quickSort l = qs l id

qs :: Ord a => [a] -> ([a] -> b) -> b
qs [] c = c []
qs (x:xs) c
  = split x xs (\lt geq -> qs lt (\ys -> qs geq (\zs -> c (ys++x:zs))))

split :: Ord a => a -> [a] -> ([a] -> [a] -> b) -> b
split x [] c = c [] []
split x (y:ys) c
  = split x ys (\lt geq -> if y < x then c (y:lt) geq else c lt (y:geq)) 


unzipC :: [(a,b)] -> ([a] -> [b] -> c) -> c
unzipC [] c = c [] []
unzipC ((x,y):xys) c = unzipC xys (\xs ys -> c (x:xs) (y:ys))

testUnzip = unzipC (zip [1..3] [4..10]) (++) == [1..6]

appEqLen = (($(++)).).(unzipC.).zip -- :D



