From oleg-at-okmij.org Fri Aug 6 20:29:40 2004 To: haskell-cafe-at-haskell.org In-Reply-To: <20040806154413.1799d9ad.Malcolm.Wallace@cs.york.ac.uk> Subject: Partial signatures Message-ID: <20040807032940.1BDE4AB7E@Adric.metnet.navy.mil> Date: Fri, 6 Aug 2004 20:29:40 -0700 (PDT) Status: RO Malcolm Wallace wrote: ] and since you cannot write a partial signature, Can't we really? It seems `partial signature' means one of two things: - we wish to add an extra constraint to the type of the function but we don't wish to explicitly write the type of the function and enumerate all of the constraints - we wish to specify the type of the function and perhaps some of the constraints -- and let the typechecker figure out the rest of the constraints. Both of the above is easily possible, in Haskell98. > module PartialSig where > import Data.Array -- for the examples below In the first case, suppose we have a function > foo x = Just x and suppose we wish to add an extra constraint (Ord x) but without specifying the full signature of the function. We just wish to add one constraint. > addOrd:: (Ord x) => x -> a > addOrd = undefined > > foo' x | False = addOrd x > foo' x = Just x Even a not-so-sufficiently smart compiler should be able to eliminate any traces of the first clause of foo' in the run code. So, the recipe is to define a function like `addOrd' (or like an identity), give it the explicit signature with the desired constraint, and then `mention' that function somewhere in the body of foo. Or, as the example above shows, prepend a clause of the form foo arg ... | False = addOrd arg ... In that case, the body of the function foo does not have to be changed at all. For the second case: suppose we wrote a function > bar a i = a ! i and wish to give it a type signature *> bar:: Array i e -> i -> e But that won't work: we must specify all the constraints: Could not deduce (Ix i) from the context () arising from use of `!' at /tmp/d.lhs:207 Probable fix: Add (Ix i) to the type signature(s) for `bar' In the definition of `bar': bar a i = a ! i But what if we wish to specify the type without the constraints (and let the compiler figure the constraints out)? Again, the same trick applies: > barSig:: Array i e -> i -> e > barSig = undefined > > bar' a i | False = barSig a i > bar' a i = a ! i Incidentally, barSig plays the role of a Java interface of a sort. barSig is a bona fide function, and can be exported and imported. To make sure that some other function baz satisfies the barSig interface (perhaps with a different set of constraints), all we need to do is to say baz arg1 ... | False = barSig arg1 ... We can also attach to barSig some constraints. The typechecker will figure out the rest, for bar' and baz.