Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How did Haskell add Turing-completeness to System F?

I've been reading up on various type systems and lambda calculi, and i see that all of the typed lambda calculi in the lambda cube are strongly normalizing rather than Turing equivalent. This includes System F, the simply typed lambda calculus plus polymorphism.

This leads me to the following questions, for which I've been unable to find any comprehensible answer:

  • How does the formalism of (e.g.) Haskell differ from the calculus on which it is ostensibly based?
  • What language features in Haskell don't fall within System F formalism?
  • What's the minimum change necessary to allow Turing complete computation?

Thank you so much to whomever helps me understand this.

like image 287
JwameeQohwiye Avatar asked Aug 12 '14 02:08

JwameeQohwiye


People also ask

Is Haskell system F?

System F formalizes parametric polymorphism in programming languages, thus forming a theoretical basis for languages such as Haskell and ML.

Is lambda calculus Turing complete?

Lambda calculus is Turing complete, that is, it is a universal model of computation that can be used to simulate any Turing machine. Its namesake, the Greek letter lambda (λ), is used in lambda expressions and lambda terms to denote binding a variable in a function. Lambda calculus may be untyped or typed.

Is Turing complete PDF?

With no recursion and no unbounded loops, PDF is clearly not Turing complete.


1 Answers

In a word, general recursion.

Haskell allows for arbitrary recursion while System F has no form of recursion. The lack of infinite types means fix isn't expressible as a closed term.

There is no primitive notion of names and recursion. In fact, pure System F has no notion of any such thing as definitions!

So in Haskell this single definition is what adds turing completeness

fix :: (a -> a) -> a fix f = let x = f x in x 

Really this function is indicative of a more general idea, by having fully recursive bindings, we get turing completeness. Notice that this applies to types, not just values.

data Rec a = Rec {unrec :: Rec a -> a}  y :: (a -> a) -> a y f = u (Rec u)   where u x = f $ unrec x x 

With infinite types we can write the Y combinator (modulo some unfolding) and through it general recursion!

In pure System F, we often have some informal notion of definitions, but these are simply shorthands that are to be mentally inlined fully. This isn't possible in Haskell as this would create infinite terms.

The kernel of Haskell terms without any notion of let, where or = is strongly normalizing, since we don't have infinite types. Even this core term calculus isn't really System F. System F has "big lambdas" or type abstraction. The full term for id in System F is

id := /\ A -> \(x : A) -> x 

This is because type inference for System F is undecidable! We explicitly notate wherever and whenever we expect polymorphism. In Haskell such a property would be annoying, so we limit the power of Haskell. In particular, we never infer a polymorphic type for a Haskell lambda argument without annotation (terms and conditions may apply). This is why in ML and Haskell

let x = exp in foo 

isn't the same as

(\x -> foo) exp 

even when exp isn't recursive! This is the crux of HM type inference and algorithm W, called "let generalization".

like image 171
Daniel Gratzer Avatar answered Sep 23 '22 23:09

Daniel Gratzer