14

id is the only function of type a -> a, and fst the only function of type (a,b) -> a. In these simple cases, this is fairly straightforward to see. But in general, how would you go about proving this? What if there are multiple possible functions of the same type?

Alternatively, given a function's type, how do you derive the unique (if this is true) function of that type?

Edit: I'm particularly interested in what happens when we start adding constraints into the types.

Mike Izbicki
  • 6,286
  • 1
  • 23
  • 53
  • 8
    To be pedantic, I think people would usually say that `id` is the only 'interesting' or 'total' function of type `a->a`. `undefined` can be of *any* type in Haskell, but it's not a useful function. You might also be interested in Djinn, a program that generates functions from a type when possible, http://lambda-the-ultimate.org/node/1178 – John L Nov 27 '12 at 00:39
  • @JohnL Djinn doesn't actually prove uniqueness, does it? It just finds some function of that type if it exists. – Mike Izbicki Nov 27 '12 at 00:42
  • 3
    This question may be more suited to http://cs.stackexchange.com – Heatsink Nov 27 '12 at 00:47
  • @MikeIzbicki that's a good point. However, Djinn will find multiple solutions (e.g. `f ? (a,a,b) -> a` will find both answers). If the list is exhaustive (I don't know if it is), then determining uniqueness is trivial. – John L Nov 27 '12 at 00:52
  • @JohnL - djinn won't generate all functions; at least not in all cases -- consider `f :: Float -> Float` – amindfv Nov 27 '12 at 02:45
  • @amindfv: Djinn has no knownledge of `Float`, or for that matter even `Int`, so if you try you'll get an error. But the point about exhaustiveness isn't that we need to find all solutions, just that we need to know how many we're looking for. I don't know if the underlying PL framework is capable of that. Anyway I thought I'd test what happens with Church-encoded numbers and `f ? Church a -> Church a -> Church a`. djinn does find quite a few solutions, bounded by the cutoff setting. Given unbounded resources and the right encoding, maybe it would produce the requisite infinite solutions? – John L Nov 27 '12 at 05:27
  • @JohnL Since Djinn works by converting the types into a first-order logic, we can solve these expressions by exhaustive search. So I think given infinite resources it should find all solutions. – Mike Izbicki Nov 27 '12 at 05:52

1 Answers1

15

The result you are looking for derives from Reynolds' parametricity, and was most famously shown by Wadler in theorems for free.

The most elegant way of proving basic parametricity results I have seen use the notion of a "Singleton Type". Essentially, given any ADT

data Nat = Zero | Succ Nat

there exists an indexed family (also known as a GADT)

data SNat n where
   SZero :: SNat Zero
   SSucc :: SNat n -> SNat (Succ n)

and we can give a semantics to our language by "erasing" all the types to an untyped language such that Nat and SNat erase to the same thing. Then, by the typing rules of the language

id (x :: SNat n) :: SNat n

SNat n has only one inhabitant (its singleton), since the semantics is given by erasure, functions can not use the type of their arguments, so the only value returnable from id on any Nat is the number you gave it. This basic argument can be extended to prove most of the parametricity results and was used by Karl Crary in A Simple Proof Technique for Parametricity Results although the presentation I have here is inspired by Stone and Harper

Philip JF
  • 28,199
  • 5
  • 70
  • 77