(* f : T1 -> T2 x : T1 y : T3 z : T4 T1 = T3 * T4 T3 = int T4 = int T2 = int f : int * int -> int *) let f x = let (y,z) = x in (abs y) + z (* sum : T1 -> T2 lst : T1 hd : T3 tl : T3 list T1 = T3 list T2 = int T3 = int *) let rec sum lst = match lst with [] -> 0 | hd::tl -> hd + (sum tl) (* length: T1 -> T2 lst : T1 T1 = T3 list hd : T3 tl : T3 lst T2 = int length : 'a list -> int *) let rec length lst = match lst with [] -> 0 | hd::tl -> 1 + (length tl) (* compose : T1 -> T2 -> T3 -> Tr f : T1 g : T2 x : T3 from g being applied to x: T2 = T3 -> T4 for some T4 from f being applied to (g x): T1 = T4 -> T5 for some T4 from that being the overall result: Tr = T5 putting all that together: T1 = T4 -> T5 T2 = T3 -> T4 Tr = T5 so compose : (T4 -> T5) -> (T3 -> T4) -> T3 -> T5 now replace unconstrained types /consistently/ with type variables: ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b which is the same as ('a -> 'b) -> ('c -> 'a) -> ('c -> 'b) *) let compose f g x = f (g x) (* have not gotten to this one yet *) let rec funnyCount f g lst1 lst2 = match lst1 with [] -> 0 (* weird, lst2 might not be empty *) | hd::tl -> (if (f hd) then 1 else 0) + funnyCount g f lst2 tl