Curry-Howard-Lambek correspondence
From HaskellWiki
(Revise intro to be more descriptive of three way correspondance; links) |
m (inhibit -> inhabit) |
||
| Line 8: | Line 8: | ||
<haskell>theAnswer :: Integer | <haskell>theAnswer :: Integer | ||
theAnswer = 42</haskell> | theAnswer = 42</haskell> | ||
| - | The logical interpretation of the program is that the type <hask>Integer</hask> is | + | The logical interpretation of the program is that the type <hask>Integer</hask> is inhabited (by the value <hask>42</hask>), so the existence of this program ''proves'' the proposition <hask>Integer</hask> (a type without any value is the "bottom" type, a proposition with no proof). |
== Inference == | == Inference == | ||
| - | A (non-trivial) Haskell function maps a value (of type <hask>a</hask>, say) to another value (of type <hask>b</hask>), therefore, ''given'' a value of type <hask>a</hask> (a proof of <hask>a</hask>), it ''constructs'' a value of type <hask>b</hask> (so the proof is ''transformed'' into a proof of <hask>b</hask>)! So <hask>b</hask> is | + | A (non-trivial) Haskell function maps a value (of type <hask>a</hask>, say) to another value (of type <hask>b</hask>), therefore, ''given'' a value of type <hask>a</hask> (a proof of <hask>a</hask>), it ''constructs'' a value of type <hask>b</hask> (so the proof is ''transformed'' into a proof of <hask>b</hask>)! So <hask>b</hask> is inhabited if <hask>a</hask> is, and a proof of <hask>a -> b</hask> is established (hence the notation, in case you were wondering). |
<haskell> | <haskell> | ||
| Line 19: | Line 19: | ||
</haskell> | </haskell> | ||
| - | says, for example, if <hask>Boolean</hask> is | + | says, for example, if <hask>Boolean</hask> is inhabited, so is <hask>Integer</hask> (well, the point here is demonstration, not discovery). |
== Connectives == | == Connectives == | ||
| Line 32: | Line 32: | ||
</haskell> | </haskell> | ||
So any one of <hask>OK String</hask>, <hask>Warning String</hask> or <hask>Error String</hask> proves the proposition <hask>Message String</hask>, leaving out any two constructors would not invalidate the program. At the same time, a proof of <hask>Message String</hask> can be pattern matched against the constructors to see which one it proves. | So any one of <hask>OK String</hask>, <hask>Warning String</hask> or <hask>Error String</hask> proves the proposition <hask>Message String</hask>, leaving out any two constructors would not invalidate the program. At the same time, a proof of <hask>Message String</hask> can be pattern matched against the constructors to see which one it proves. | ||
| - | On the other hand, to prove <hask>String</hask> is | + | On the other hand, to prove <hask>String</hask> is inhabited from the proposition <hask>Message String</hask>, it has to be proven that you can prove <hask>String</hask> from any of the alternatives... |
<haskell> | <haskell> | ||
show :: Message String -> String | show :: Message String -> String | ||
| Line 65: | Line 65: | ||
</haskell> | </haskell> | ||
| - | means, logically, there is a type <hask>a</hask> for which the type <hask>a -> a -> Bool</hask> is | + | means, logically, there is a type <hask>a</hask> for which the type <hask>a -> a -> Bool</hask> is inhabited, or, from <hask>a</hask> it can be proved that <hask>a -> a -> Bool</hask> (the class promises two different proofs for this, having names <hask>==</hask> and <hask>/=</hask>). |
This proposition is of existential nature (not to be confused with [[existential type]]). A proof for this proposition (that there is a type that conforms to the specification) is (obviously) a set of proofs of the advertized proposition (an implementation), by an <hask>instance</hask> | This proposition is of existential nature (not to be confused with [[existential type]]). A proof for this proposition (that there is a type that conforms to the specification) is (obviously) a set of proofs of the advertized proposition (an implementation), by an <hask>instance</hask> | ||
declaration: | declaration: | ||
Revision as of 13:48, 18 November 2006
The Curry-Howard-Lambek correspondance is a three way isomorphism between types (in programming languages), propositions (in logic) and objects of a Cartesian closed category. Interestingly, the isomorphism maps programs (functions in Haskell) to (constructive) proofs in logic (and vice versa).
Contents |
1 The Answer
As is well established by now,
theAnswer :: Integer theAnswer = 42
2 Inference
A (non-trivial) Haskell function maps a value (of typerepresentation :: Bool -> Integer representation False = 0 representation True = 1
3 Connectives
Of course, atomic propositions contribute little towards knowledge, and the Haskell type system incorporates the logical connectives
and
, though heavily disguised.
Haskell handles
conjuction in the manner described by Intuitionistic Logic. When a program has type
, the value returned itself indicates which one. The algebraic data types in Haskell has a tag on each alternative, the constructor, to indicate the injections:
data Message a = OK a | Warning a | Error a p2pShare :: Integer -> Message String p2pShare n | n == 0 = Warning "Share! Freeloading hurts your peers." | n < 0 = Error "You cannot possibly share a negative number of files!" | n > 0 = OK ("You are sharing " ++ show n ++ " files."
show :: Message String -> String show (OK s) = s show (Warning s) = "Warning: " ++ s show (Error s) = "ERROR! " ++ s
The
conjuction is handled via an isomorphism in Closed Cartesian Categories in general (Haskell types belong to this category):
.
That is, instead of a function from
to Z, we can have a function that takes an argument of type X and returns another function of type
, that is, a function that takes Y to give (finally) a result of type Z: this technique is (known as currying) logically means
.
(insert quasi-funny example here)
So in Haskell, currying takes care of the
connective. Logically, a proof of
is a pair (a,b) of proofs of the propositions. In Haskell, to have the final C value, values of both A and B have to be supplied (in turn) to the (curried) function.
4 Theorems for free!
Things get interesting when polymorphism comes in. The composition operator in Haskell proves a very simple theorem.
(.) :: (a -> b) -> (b -> c) -> (a -> c) (.) f g x = f (g x)
5 Type classes
A type class in Haskell is a proposition about a type.
class Eq a where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool
declaration:
instance Eq Bool where True == True = True False == False = True _ == _ = False (/=) a b = not (a == b)
A not-so-efficient Quicksort implementation would be:
quickSort [] = [] quickSort (x : xs) = quickSort lower ++ [x] ++ quickSort higher where lower = filter (<= x) xs higher = filter (> x) xs
6 Multi-parameter type classes
Haskell makes frequent use of multiparameter type classes. Type classes use a logic language (Prolog-like), and for multiparamter type classes they define a relation between types.
6.1 Functional dependencies
These type level functions are set-theoretic. That is,7 Indexed types
(please someone complete this, should be quite interesting, I have no idea what it should look like logically)
