Skip to content

Instantly share code, notes, and snippets.

@jcoglan
Last active May 2, 2018 21:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jcoglan/b3df49a8999d5ad12f8fd82cecbf39d2 to your computer and use it in GitHub Desktop.
Save jcoglan/b3df49a8999d5ad12f8fd82cecbf39d2 to your computer and use it in GitHub Desktop.

Haskell

There follows an extremely rough approximation to Haskell's type checker, written as a logic program. Mostly to explore type inference and syntactic sugar.

For the most part, we won't need a lot of syntactic checks in this implementation, but for terms with no internal structure, like variables and numbers, it's useful to specify their members.

syntax {
  $x ::= a / b / c / d / e / f / g / h / i / j
       / k / l / m / n / o / p / q / r / s / t
       / u / v / w / x / y / z

  $n ::= 0 / 1 / 2 / 3 / 4 / 5 / 6 / 7 / 8 / 9
}

Lambda calculus

This is a minor variation on the simply typed lambda calculus. The major difference is that the parameter of an abstraction is not annotated with a type; the type is inferred from use of the parameter in the body.

A variable x has type T in typing context Γ if a binding x : T appears in Γ. The meaning of is defined below.

rule T-Var {
  ($x : $T) ∈ $Γ
  --------------
   $Γ ⊢ $x :: $T
}

An abstraction \x -> t2 has type T1 → T2 if, in the context Γ augmented with the assumption that x has type T1, the body t2 has type T2.

rule T-Abs {
    ($Γ, $x : $T1) ⊢ $t2 :: $T2
  --------------------------------
  $Γ ⊢ (\$x -> $t2) :: ($T1 → $T2)
}

An application t1 t2 has type T2 if the function t1 has type T1 → T2 and the argument t2 has type T1. No subtyping is currently supported, and neither are type aliases.

rule T-App {
  $Γ ⊢ $t1 :: ($T1 → $T2) / $Γ ⊢ $t2 :: $T1
  -----------------------------------------
            $Γ ⊢ ($t1 $t2) :: $T2
}

Typing context

A typing context Γ holds the types of any in-scope abstraction parameters. Syntactically, a context is either the empty context , or a context augmented with a new binding, i.e. Γ, x : T.

The binding x : T is a member of the context, if this binding appears at the end of the context, means it was pushed most recently. A cut is used here to cope with variable shadowing.

rule T-Var-0 <!> {
  ($x : $T) ∈ ($Γ, $x : $T)
}

The recursive case searches for x : T if it does not appear as the final element.

rule T-Var-N {
         ($x1 : $T1) ∈ $Γ
  -----------------------------
  ($x1 : $T1) ∈ ($Γ, $x2 : $T2)
}

Type classes

This is a gross hack and just exists to support the few constrained types defined below. A function fn has type T if the function has the constrained type (C S) ⇒ T and an instance declaration instance C S exists. The idea is that the type variable S appears within T and the constraint can be checked once S is instantiated.

rule T-TypeClass {
  $Γ ⊢ $fn :: ($C $S) ⇒ $T / instance $C $S
  -----------------------------------------
                $Γ ⊢ $fn :: $T
}

Numbers

Numbers have the type Num p ⇒ p.

rule T-Num {
  $Γ ⊢ $n :: (Num $p) ⇒ $p
}

Sugar

Now we augment the basic lambda calculus syntax with the capacity for dynamically-defined sugar. A term t has the type T if t can be rewritten as s, and s has the type T.

rule T-Sugar {
  $t ~> $s / $Γ ⊢ $s :: $T
  ------------------------
        $Γ ⊢ $t :: $T
}

Infix operators

One instance of syntactic sugar is infix operators; the expression x + y can be rewritten as (+ x) y, where have added parentheses because the core language only defines application of a function to a single argument.

If an infix declaration exists for operator o, then rewrite t1 o t2 as (o t1) t2. We don't have infixl and infixr because all terms in this implementation are fully parenthesised to show precedence and associativity.

rule S-Infix {
            infix $o
  ------------------------------
  ($t1 $o $t2) ~> (($o $t1) $t2)
}

Do-notation

Do-notation in Haskell rewrites

do { x <- t1 ; t2... }

as

t1 >>= \x -> do { t2... }

In our notation, a sequence of actions is written as a nested list, so we write do (x <- t1 t2) where t2 is a compound expression containing the rest of the do-block.

rule S-DoBind <!> {
  (do ($x <- $t1 $t2)) ~> ($t1 >>= (\$x -> (do $t2)))
}

If the above rule does not match, we fall through and strip off the do from a non-assignment line. It's assumed that this is the last line in the block.

rule S-DoEnd {
  (do $t) ~> $t
}

Built-in types

These instance declarations tell us which typeclass each type is an instance of, and are used with the T-TypeClass rule above.

rule C-Int-Num     { instance Num Int     }
rule C-Int-Read    { instance Read Int    }
rule C-Int-Show    { instance Show Int    }
rule C-IO-Functor  { instance Functor IO  }
rule C-IO-Monad    { instance Monad IO    }
rule C-String-Show { instance Show String }

Function definitions

Finally, a few definitions of prelude functions. Most of these types are copied verbatim from ghci.

+ takes two Num-compatible types and returns another. It is also an infix operator.

rule F-Plus {
  $Γ ⊢ + :: (Num $a) ⇒ ($a → ($a → $a))
}
rule I-Plus { infix + }

++ takes two strings and returns another, and is also an infix operator. Strictly speaking, this function should have type [a] → [a] → [a], but we don't have type aliases in this implementation.

# $Γ ⊢ ++ :: ([$a] → ([$a] → [$a]))

rule F-Cat {
  $Γ ⊢ ++ :: (String → (String → String))
}
rule I-Cat { infix ++ }

fmap maps over a functor, for example we can use it to convert the contents of an IO by calling fmap read io.

rule F-Fmap {
  $Γ ⊢ fmap :: (Functor $f) ⇒ (($a → $b) → (($f $a) → ($f $b)))
}

Now, the monadic functions. return lifts a value into an instance of the required monad. Which monad m is required is inferred from context.

rule F-Return {
  $Γ ⊢ return :: (Monad $m) ⇒ ($a → ($m $a))
}

Bind, or >>=, takes a monadic value, applies a function to its contents, and returns another monadic value in the same monad holding the result. It is an infix operator; so desugaring do { x <- t1 ; t2 } leads to t1 >>= \x -> do t2..., which further leads to (>>= t1) (\x -> do t2...).

rule F-Bind {
  $Γ ⊢ >>= :: (Monad $m) ⇒ (($m $a) → (($a → ($m $b)) → ($m $b)))
}
rule I-Bind { infix >>= }

read takes a string and returns a value of the type required by the calling context.

rule F-Read {
  $Γ ⊢ read :: (Read $a) ⇒ (String → $a)
}

getLine is used to read a line from stdin, and as it requires an effect, returns IO String.

rule F-GetLine {
  $Γ ⊢ getLine :: (IO String)
}

putStrLn is the opposite of getLine, it writes a line to stdout and so takes a string, executes an effect and returns nothing, or IO ∅. We use because parens are one of the few reserved tokens in this system.

rule F-PutStrLn {
  $Γ ⊢ putStrLn :: (String → (IO ∅))
}

Finally, print takes any Show value and prints it, again returning IO ().

rule F-Print {
  $Γ ⊢ print :: (Show $a) ⇒ ($a → (IO ∅))
}
∅ ⊢ 4 :: Int
———————————————————————— T-Num ———————————————— C-Int-Num
∅ ⊢ 4 :: (Num Int) ⇒ Int instance Num Int
————————————————————————————————————————————————— T-TypeClass
∅ ⊢ 4 :: Int
∅ ⊢ ((3 + 4) + (5 + 6)) :: $T
———————————————————————————————————————— F-Plus ———————————————— C-Int-Num ———————————————————————— T-Num ———————————————— C-Int-Num
∅ ⊢ + :: (Num Int) ⇒ (Int → (Int → Int)) instance Num Int ∅ ⊢ 3 :: (Num Int) ⇒ Int instance Num Int
—————————————————————————————————————————————————————————————————— T-TypeClass ————————————————————————————————————————————————— T-TypeClass ———————————————————————— T-Num ———————————————— C-Int-Num ———————————————————————————————————————— F-Plus ———————————————— C-Int-Num ———————————————————————— T-Num ———————————————— C-Int-Num
∅ ⊢ + :: (Int → (Int → Int)) ∅ ⊢ 3 :: Int ∅ ⊢ 4 :: (Num Int) ⇒ Int instance Num Int ∅ ⊢ + :: (Num Int) ⇒ (Int → (Int → Int)) instance Num Int ∅ ⊢ 5 :: (Num Int) ⇒ Int instance Num Int
——————— I-Plus ———————————————————————————————————————————————————————————————————————————————————————————— T-App ————————————————————————————————————————————————— T-TypeClass —————————————————————————————————————————————————————————————————— T-TypeClass ————————————————————————————————————————————————— T-TypeClass ———————————————————————— T-Num ———————————————— C-Int-Num
infix + ∅ ⊢ (+ 3) :: (Int → Int) ∅ ⊢ 4 :: Int ∅ ⊢ + :: (Int → (Int → Int)) ∅ ⊢ 5 :: Int ∅ ⊢ 6 :: (Num Int) ⇒ Int instance Num Int
———————————————————————————————————————— F-Plus ———————————————— C-Int-Num ———————————————————— S-Infix —————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-App ——————— I-Plus ———————————————————————————————————————————————————————————————————————————————————————————— T-App ————————————————————————————————————————————————— T-TypeClass
∅ ⊢ + :: (Num Int) ⇒ (Int → (Int → Int)) instance Num Int (3 + 4) ~> ((+ 3) 4) ∅ ⊢ ((+ 3) 4) :: Int infix + ∅ ⊢ (+ 5) :: (Int → Int) ∅ ⊢ 6 :: Int
—————————————————————————————————————————————————————————————————— T-TypeClass ——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-Sugar ———————————————————— S-Infix —————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-App
∅ ⊢ + :: (Int → (Int → Int)) ∅ ⊢ (3 + 4) :: Int (5 + 6) ~> ((+ 5) 6) ∅ ⊢ ((+ 5) 6) :: Int
——————— I-Plus ———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-App ——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-Sugar
infix + ∅ ⊢ (+ (3 + 4)) :: (Int → Int) ∅ ⊢ (5 + 6) :: Int
———————————————————————————————————————————— S-Infix ————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-App
((3 + 4) + (5 + 6)) ~> ((+ (3 + 4)) (5 + 6)) ∅ ⊢ ((+ (3 + 4)) (5 + 6)) :: Int
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-Sugar
∅ ⊢ ((3 + 4) + (5 + 6)) :: Int
∅ ⊢ (\x -> x) :: $T
————————————————————— T-Var-0
(x : T) ∈ (∅ , x : T)
————————————————————— T-Var
(∅ , x : T) ⊢ x :: T
————————————————————————— T-Abs
∅ ⊢ (\ x -> x) :: (T → T)
∅ ⊢ (\x -> (putStrLn x)) :: $T
——————————————————————————————— T-Var-0
(x : String) ∈ (∅ , x : String)
———————————————————————————————————————————————— F-PutStrLn ——————————————————————————————— T-Var
(∅ , x : String) ⊢ putStrLn :: (String → (IO ∅)) (∅ , x : String) ⊢ x :: String
———————————————————————————————————————————————————————————————————————————————————————————— T-App
(∅ , x : String) ⊢ (putStrLn x) :: (IO ∅)
—————————————————————————————————————————————— T-Abs
∅ ⊢ (\ x -> (putStrLn x)) :: (String → (IO ∅))
∅ ⊢ (>>= getLine) :: $T
———————————————————————————————————————————————————————————————————— F-Bind ————————————————— C-IO-Monad
∅ ⊢ >>= :: (Monad IO) ⇒ ((IO String) → ((String → (IO b)) → (IO b))) instance Monad IO
——————————————————————————————————————————————————————————————————————————————————————————————— T-TypeClass —————————————————————————— F-GetLine
∅ ⊢ >>= :: ((IO String) → ((String → (IO b)) → (IO b))) ∅ ⊢ getLine :: (IO String)
———————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-App
∅ ⊢ (>>= getLine) :: ((String → (IO b)) → (IO b))
∅ ⊢ (do (s <- getLine (t <- getLine (putStrLn (s ++ t))))) :: $T
——————————————————————————————— T-Var-0
(s : String) ∈ (∅ , s : String)
—————————————————————————————————————————————— T-Var-N
(s : String) ∈ ((∅ , s : String) , t : String)
———————————————————————————————————————————————————————————————————— F-Cat —————————————————————————————————————————————— T-Var —————————————————————————————————————————————— T-Var-0
((∅ , s : String) , t : String) ⊢ ++ :: (String → (String → String)) ((∅ , s : String) , t : String) ⊢ s :: String (t : String) ∈ ((∅ , s : String) , t : String)
———————— I-Cat —————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-App —————————————————————————————————————————————— T-Var
infix ++ ((∅ , s : String) , t : String) ⊢ (++ s) :: (String → String) ((∅ , s : String) , t : String) ⊢ t :: String
—————————————————————— S-Infix ————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-App
(s ++ t) ~> ((++ s) t) ((∅ , s : String) , t : String) ⊢ ((++ s) t) :: String
——————————————————————————————————————————————————————————————— F-PutStrLn ———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-Sugar
((∅ , s : String) , t : String) ⊢ putStrLn :: (String → (IO ∅)) ((∅ , s : String) , t : String) ⊢ (s ++ t) :: String
——————————————————————————————————————————————————————————————————————————————————— F-Bind ————————————————— C-IO-Monad ——————————————————————————————————————————————— S-DoEnd ————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-App
(∅ , s : String) ⊢ >>= :: (Monad IO) ⇒ ((IO String) → ((String → (IO ∅)) → (IO ∅))) instance Monad IO (do (putStrLn (s ++ t))) ~> (putStrLn (s ++ t)) ((∅ , s : String) , t : String) ⊢ (putStrLn (s ++ t)) :: (IO ∅)
—————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-TypeClass ————————————————————————————————————————— F-GetLine —————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-Sugar
(∅ , s : String) ⊢ >>= :: ((IO String) → ((String → (IO ∅)) → (IO ∅))) (∅ , s : String) ⊢ getLine :: (IO String) ((∅ , s : String) , t : String) ⊢ (do (putStrLn (s ++ t))) :: (IO ∅)
————————— I-Bind —————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-App ————————————————————————————————————————————————————————————————————————— T-Abs
infix >>= (∅ , s : String) ⊢ (>>= getLine) :: ((String → (IO ∅)) → (IO ∅)) (∅ , s : String) ⊢ (\ t -> (do (putStrLn (s ++ t)))) :: (String → (IO ∅))
———————————————————————————————————————————————————————————————————————————————————————————————————— S-Infix —————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-App
(getLine >>= (\ t -> (do (putStrLn (s ++ t))))) ~> ((>>= getLine) (\ t -> (do (putStrLn (s ++ t))))) (∅ , s : String) ⊢ ((>>= getLine) (\ t -> (do (putStrLn (s ++ t))))) :: (IO ∅)
———————————————————————————————————————————————————————————————————— F-Bind ————————————————— C-IO-Monad —————————————————————————————————————————————————————————————————————————————————————————— S-DoBind —————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-Sugar
∅ ⊢ >>= :: (Monad IO) ⇒ ((IO String) → ((String → (IO ∅)) → (IO ∅))) instance Monad IO (do (t <- getLine (putStrLn (s ++ t)))) ~> (getLine >>= (\ t -> (do (putStrLn (s ++ t))))) (∅ , s : String) ⊢ (getLine >>= (\ t -> (do (putStrLn (s ++ t))))) :: (IO ∅)
——————————————————————————————————————————————————————————————————————————————————————————————— T-TypeClass —————————————————————————— F-GetLine ——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-Sugar
∅ ⊢ >>= :: ((IO String) → ((String → (IO ∅)) → (IO ∅))) ∅ ⊢ getLine :: (IO String) (∅ , s : String) ⊢ (do (t <- getLine (putStrLn (s ++ t)))) :: (IO ∅)
————————— I-Bind ———————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-App ————————————————————————————————————————————————————————————————————————— T-Abs
infix >>= ∅ ⊢ (>>= getLine) :: ((String → (IO ∅)) → (IO ∅)) ∅ ⊢ (\ s -> (do (t <- getLine (putStrLn (s ++ t))))) :: (String → (IO ∅))
—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— S-Infix —————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-App
(getLine >>= (\ s -> (do (t <- getLine (putStrLn (s ++ t)))))) ~> ((>>= getLine) (\ s -> (do (t <- getLine (putStrLn (s ++ t)))))) ∅ ⊢ ((>>= getLine) (\ s -> (do (t <- getLine (putStrLn (s ++ t)))))) :: (IO ∅)
———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— S-DoBind ———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-Sugar
(do (s <- getLine (t <- getLine (putStrLn (s ++ t))))) ~> (getLine >>= (\ s -> (do (t <- getLine (putStrLn (s ++ t)))))) ∅ ⊢ (getLine >>= (\ s -> (do (t <- getLine (putStrLn (s ++ t)))))) :: (IO ∅)
—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-Sugar
∅ ⊢ (do (s <- getLine (t <- getLine (putStrLn (s ++ t))))) :: (IO ∅)
∅ ⊢ (do (x <- ((fmap read) getLine) (y <- ((fmap read) getLine) (print (x + y))))) :: $T
————————————————————————— T-Var-0
(x : Int) ∈ (∅ , x : Int)
———————————————————————————————————————————————————————————————— F-Plus ———————————————— C-Int-Num ————————————————————————————————————— T-Var-N
((∅ , x : Int) , y : Int) ⊢ + :: (Num Int) ⇒ (Int → (Int → Int)) instance Num Int (x : Int) ∈ ((∅ , x : Int) , y : Int)
—————————————————————————————————————————————————————————————————————————————————————————— T-TypeClass ————————————————————————————————————— T-Var ————————————————————————————————————— T-Var-0
((∅ , x : Int) , y : Int) ⊢ + :: (Int → (Int → Int)) ((∅ , x : Int) , y : Int) ⊢ x :: Int (y : Int) ∈ ((∅ , x : Int) , y : Int)
——————— I-Plus —————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-App ————————————————————————————————————— T-Var
infix + ((∅ , x : Int) , y : Int) ⊢ (+ x) :: (Int → Int) ((∅ , x : Int) , y : Int) ⊢ y :: Int
—————————————————————————————————————————————————————————————————————————————————— F-Fmap ——————————————————— C-IO-Functor ——————————————————————————————————————————————————— F-Read ————————————————— C-Int-Read ———————————————————————————————————————————————————————————————— F-Print ————————————————— C-Int-Show ———————————————————— S-Infix ————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-App
(∅ , x : Int) ⊢ fmap :: (Functor IO) ⇒ ((String → Int) → ((IO String) → (IO Int))) instance Functor IO (∅ , x : Int) ⊢ read :: (Read Int) ⇒ (String → Int) instance Read Int ((∅ , x : Int) , y : Int) ⊢ print :: (Show Int) ⇒ (Int → (IO ∅)) instance Show Int (x + y) ~> ((+ x) y) ((∅ , x : Int) , y : Int) ⊢ ((+ x) y) :: Int
——————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-TypeClass —————————————————————————————————————————————————————————————————————————————— T-TypeClass ———————————————————————————————————————————————————————————————————————————————————————————— T-TypeClass ——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-Sugar
(∅ , x : Int) ⊢ fmap :: ((String → Int) → ((IO String) → (IO Int))) (∅ , x : Int) ⊢ read :: (String → Int) ((∅ , x : Int) , y : Int) ⊢ print :: (Int → (IO ∅)) ((∅ , x : Int) , y : Int) ⊢ (x + y) :: Int
—————————————————————————————————————————————————————————————————————————— F-Bind ————————————————— C-IO-Monad ——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-App —————————————————————————————————————— F-GetLine ——————————————————————————————————————— S-DoEnd ——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-App
(∅ , x : Int) ⊢ >>= :: (Monad IO) ⇒ ((IO Int) → ((Int → (IO ∅)) → (IO ∅))) instance Monad IO (∅ , x : Int) ⊢ (fmap read) :: ((IO String) → (IO Int)) (∅ , x : Int) ⊢ getLine :: (IO String) (do (print (x + y))) ~> (print (x + y)) ((∅ , x : Int) , y : Int) ⊢ (print (x + y)) :: (IO ∅)
————————————————————————————————————————————————————————————————————————————————————————————————————— T-TypeClass —————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-App —————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-Sugar
(∅ , x : Int) ⊢ >>= :: ((IO Int) → ((Int → (IO ∅)) → (IO ∅))) (∅ , x : Int) ⊢ ((fmap read) getLine) :: (IO Int) ((∅ , x : Int) , y : Int) ⊢ (do (print (x + y))) :: (IO ∅)
—————————————————————————————————————————————————————————————————————— F-Fmap ——————————————————— C-IO-Functor ——————————————————————————————————————— F-Read ————————————————— C-Int-Read ————————— I-Bind ——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-App ——————————————————————————————————————————————————————————————— T-Abs
∅ ⊢ fmap :: (Functor IO) ⇒ ((String → Int) → ((IO String) → (IO Int))) instance Functor IO ∅ ⊢ read :: (Read Int) ⇒ (String → Int) instance Read Int infix >>= (∅ , x : Int) ⊢ (>>= ((fmap read) getLine)) :: ((Int → (IO ∅)) → (IO ∅)) (∅ , x : Int) ⊢ (\ y -> (do (print (x + y)))) :: (Int → (IO ∅))
——————————————————————————————————————————————————————————————————————————————————————————————————— T-TypeClass —————————————————————————————————————————————————————————————————— T-TypeClass ———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— S-Infix ————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-App
∅ ⊢ fmap :: ((String → Int) → ((IO String) → (IO Int))) ∅ ⊢ read :: (String → Int) (((fmap read) getLine) >>= (\ y -> (do (print (x + y))))) ~> ((>>= ((fmap read) getLine)) (\ y -> (do (print (x + y))))) (∅ , x : Int) ⊢ ((>>= ((fmap read) getLine)) (\ y -> (do (print (x + y))))) :: (IO ∅)
—————————————————————————————————————————————————————————————— F-Bind ————————————————— C-IO-Monad ——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-App —————————————————————————— F-GetLine —————————————————————————————————————————————————————————————————————————————————————————————————————————————— S-DoBind ——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-Sugar
∅ ⊢ >>= :: (Monad IO) ⇒ ((IO Int) → ((Int → (IO ∅)) → (IO ∅))) instance Monad IO ∅ ⊢ (fmap read) :: ((IO String) → (IO Int)) ∅ ⊢ getLine :: (IO String) (do (y <- ((fmap read) getLine) (print (x + y)))) ~> (((fmap read) getLine) >>= (\ y -> (do (print (x + y))))) (∅ , x : Int) ⊢ (((fmap read) getLine) >>= (\ y -> (do (print (x + y))))) :: (IO ∅)
————————————————————————————————————————————————————————————————————————————————————————— T-TypeClass ———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-App ——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-Sugar
∅ ⊢ >>= :: ((IO Int) → ((Int → (IO ∅)) → (IO ∅))) ∅ ⊢ ((fmap read) getLine) :: (IO Int) (∅ , x : Int) ⊢ (do (y <- ((fmap read) getLine) (print (x + y)))) :: (IO ∅)
————————— I-Bind ———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-App ———————————————————————————————————————————————————————————————————————————————— T-Abs
infix >>= ∅ ⊢ (>>= ((fmap read) getLine)) :: ((Int → (IO ∅)) → (IO ∅)) ∅ ⊢ (\ x -> (do (y <- ((fmap read) getLine) (print (x + y))))) :: (Int → (IO ∅))
—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— S-Infix ——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-App
(((fmap read) getLine) >>= (\ x -> (do (y <- ((fmap read) getLine) (print (x + y)))))) ~> ((>>= ((fmap read) getLine)) (\ x -> (do (y <- ((fmap read) getLine) (print (x + y)))))) ∅ ⊢ ((>>= ((fmap read) getLine)) (\ x -> (do (y <- ((fmap read) getLine) (print (x + y)))))) :: (IO ∅)
———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— S-DoBind ————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-Sugar
(do (x <- ((fmap read) getLine) (y <- ((fmap read) getLine) (print (x + y))))) ~> (((fmap read) getLine) >>= (\ x -> (do (y <- ((fmap read) getLine) (print (x + y)))))) ∅ ⊢ (((fmap read) getLine) >>= (\ x -> (do (y <- ((fmap read) getLine) (print (x + y)))))) :: (IO ∅)
———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— T-Sugar
∅ ⊢ (do (x <- ((fmap read) getLine) (y <- ((fmap read) getLine) (print (x + y))))) :: (IO ∅)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment