(* the signature is general and the structures are the implementation *) signature abstractFunction = sig type element1; type element2; type element3; val f1: element1 -> element2; val f2: element1 -> element3; end; structure concreteFunction1:abstractFunction = struct type element1 = int; type element2 = bool; type element3 = int; fun f1 (i) = i=2; fun f2 (i) = i+2; end; structure concreteFunction2:abstractFunction = struct type element1 = int; type element2 = bool; type element3 = bool; fun f1 (i) = i>2; fun f2 (i) = i < 2; end; (* works because the types of the function are the same *) val l1 = [concreteFunction1.f1, concreteFunction2.f1]; (* doesn't work because the types of the function are different *) val l2 = [concreteFunction1.f2, concreteFunction2.f2];