| Safe Haskell | None | 
|---|---|
| Language | Haskell2010 | 
Language.PTS.Examples.Identity
Description
Identity function is used often to demonstrate polymorphic calculus. This is not an exception.
Documentation
stlcUnitIdentity :: Term STLC Source #
In simple typed lambda calculus one have to define separate functions for different types, even they have same shape.
>>>demo_ basicCtx stlcUnitIdentityλ x → x : Unit → Unit ↪ λ x → x : Unit → Unit
demo_ prints the term, result of evaluation and checked type
term ↪ value : type
stlcBoolIdentity :: Term STLC Source #
Next we can write identity function for booleans:
>>>demo_ basicCtx stlcBoolIdentityλ x → x : Bool → Bool ↪ λ x → x : Bool → Bool
If we would write the type-inferencer for STLC (TODO), it would need to default types for such intristically polymorphic values.
As this is the first example, let's see evaluator and type-checker in action:
>>>demo_ basicCtx ("True" :: Term STLC)True ↪ True : Bool
Next we apply True to the identity function:
>>>demo_ basicCtx $ stlcBoolIdentity @@ "True"(λ x → x : Bool → Bool) True ↪ True : Bool
If we apply the value of wrong type, we get an error:
>>>demo_ basicCtx $ stlcBoolIdentity @@ "TT"error: • Couldn't match expected type Bool with actual type Unit • In the expression: TT • when checking expression (λ x → x : Bool → Bool) TT
Because the library is based on PTS, we could try to apply a type too, but that's also a type-error:
>>>demo_ basicCtx $ stlcBoolIdentity @@ "Bool"error: • Couldn't match expected type Bool with actual type ⋆ • In the expression: Bool • when checking expression (λ x → x : Bool → Bool) Bool
polymorphicIdentity :: Specification s => Term s Source #
Because simply typed lambda calculus is restrictive, we have polymorphic calculi.
In language-pts we can define the term once and for all specications.
systemfIdentity :: Term SystemF Source #
However let's experiment with SystemF first.
>>>demo_ emptyCtx systemfIdentityλ a x → x : ∀ a → a → a ↪ λ a x → x : ∀ a → a → a
Note: emptyCtx. We can apply values.
 When we apply a Bool we get boolean identity function,
 and further we can apply a Value
>>>demo_ basicCtx $ systemfIdentity @@ "Bool"(λ a x → x : ∀ a → a → a) Bool ↪ λ x → x : Bool → Bool
>>>demo_ basicCtx $ systemfIdentity @@ "Bool" @@ "False"(λ a x → x : ∀ a → a → a) Bool False ↪ False : Bool
As with STLC, we get type-error if we apply value of wrong type:
>>>demo_ basicCtx $ systemfIdentity @@ "Unit" @@ "False"error: • Couldn't match expected type Unit with actual type Bool • In the expression: False • when checking expression (λ a x → x : ∀ a → a → a) Unit False
And "sort" error, if we try to apply value directly!
>>>demo_ basicCtx $ systemfIdentity @@ "False"error: • Couldn't match expected type ⋆ with actual type Bool • In the expression: False • when checking expression (λ a x → x : ∀ a → a → a) False
stlcIdentity :: Term STLC Source #
Note: we can write polymorphic looking identity function in PTS for STLC, but it won't typecheck:
>>>demo_ emptyCtx stlcIdentityerror: • No PTS Rule (□,⋆,-) • when checking expression λ a x → x : ∀ a → a → a
hindleyMilnerIdentity :: Term HindleyMilner Source #
In Haskell we can apply identity function to itself
>>>:t id idid id :: a -> a
GHCs "type-checker" (actually inferrer) infers the following value.
 Note that all applied types are simple, monomorphic types (no forall_):
>>>demo_ emptyCtx $ lam_ "b" (systemfIdentity @@ ("b" ~> "b") @@ (systemfIdentity @@ "b")) -:- forall_ "b" ("b" ~> "b")λ b → (λ a x → x : ∀ a → a → a) (b → b) ((λ a x → x : ∀ a → a → a) b) : ∀ b → b → b ↪ λ b x → x : ∀ b → b → b
Alternatively, different value can be inferred (AFAIK that's what Agda would do).
 Here, as we don't abstract (lam_), we don't need annotations, due bi-directional type-checking in language-pts!
>>>demo_ emptyCtx $ systemfIdentity @@ forall_ "b" ("b" ~> "b") @@@ systemfIdentity(λ a x → x : ∀ a → a → a) (∀ b → b → b) (λ a x → x : ∀ a → a → a) ↪ λ a x → x : ∀ b → b → b
But this won't type-check in predicative System F (= Hindley-Milner, HindleyMilner) system:
>>>demo_ emptyCtx $ hindleyMilnerIdentity @@ forall_ "b" ("b" ~> "b") @@@ hindleyMilnerIdentityerror: • Couldn't match expected type M with actual type P • In the expression: ∀ b → b → b • when checking expression (λ a x → x : ∀ a → a → a) (∀ b → b → b) (λ a x → x : ∀ a → a → a) (∀ b → b → b) (λ a x → x : ∀ a → a → a)
Former is however, ok. Note that we get a polymorphic value!
>>>demo_ emptyCtx $ Ann (lam_ "b" (hindleyMilnerIdentity @@ ("b" ~> "b") @@ (hindleyMilnerIdentity @@ "b"))) (forall_ "b" ("b" ~> "b"))λ b → (λ a x → x : ∀ a → a → a) (b → b) ((λ a x → x : ∀ a → a → a) b) : ∀ b → b → b ↪ λ b x → x : ∀ b → b → b