
s = \x y z -> x z (y z)
k = \x y -> x
i = \x -> x

c = \f x y -> f y x
b = \f g x -> f (g x)

w = c s i
c' = \f x -> s f (k x)
b' = b (s b) k

-- this file gives the following types:
-- *Main> :t w
-- w :: (t -> t -> t1) -> t -> t1
-- *Main> :t c'
-- c' :: (t -> t1 -> t2) -> t1 -> t -> t2
-- *Main> :t b'
-- b' :: (t2 -> t) -> (t -> t1) -> t2 -> t1

-- example of how you might use the Haskell typechecker to check
-- steps in your answer: if asked to reduce s k k

i0 = s k k
i1 = (\x y z -> x z (y z)) k k
i2 = (\y z -> k z (y z)) k
i3 = (\z -> k z (k z))
i4 = (\z -> (\x y -> x) z ((\x y -> x) z))
i5 = (\z -> (\y -> z) (\y -> z))
i6 = (\z -> z)

-- then do 
-- *Main> :t i0
-- i0 :: t -> t
-- *Main> :t i3
-- i3 :: t -> t
-- *Main> :t i6
-- i6 :: t -> t
-- etc 

-- note that if it had given you 
-- i6 :: t1 -> t1
-- this would be the same type, just a different choice of variable

