Difference from JavaScript
f = fn(x){ printn(x) }
f(2) //→ 2
• No semicolon
• s/func/on/fn/
RubyKaigi 2015 5
Slide 6
Slide 6 text
Myself
• @yhara (Yutaka Hara)
• (Matsue, Shimane)
• Making so9ware with Ruby
RubyKaigi 2015 6
Slide 7
Slide 7 text
My blog1
1 h$p:/
/route477.net/d/
RubyKaigi 2015 7
Slide 8
Slide 8 text
Me and Ruby
• Enumerable#lazy (Ruby 2.0~)
• Note: I'm not a Ruby
commi>er
• TRICK judge
• ʰRubyͰ࡞Δحົͳϓϩάϥ
ϛϯάݴޠʱ(Making Esoteric
Language with Ruby)
RubyKaigi 2015 8
Slide 9
Slide 9 text
1. What is "Type Inference"?
RubyKaigi 2015 9
Slide 10
Slide 10 text
What is "Type"?
• Type = Group of values
• 1,2,3, ... => Integer
• "a", "b", "c", ... => String
RubyKaigi 2015 10
Slide 11
Slide 11 text
What is "Type"?
• Ruby has type, too! (Integer, String,...)
• Ruby variables do not have type, though
a = 1
a = "str" # ok
• This is error in C
int a = 1;
a = "str"; // compile error!
RubyKaigi 2015 11
Slide 12
Slide 12 text
Pros of sta)c typing
1. Op%miza%on
2. Type check
def foo(user)
print user.name
end
foo(123)
#=> NoMethodError: undefined method `name' for 123:Fixnum
RubyKaigi 2015 12
Slide 13
Slide 13 text
Cons of sta)c typing
• Type annota+on?
Array ary = [1,2,3]
ary.map{|Integer x|
x.to_s
}
RubyKaigi 2015 13
Slide 14
Slide 14 text
Type inference
-- Haskell
ary = [1,2,3]
map (\x -> show x) ary
• No type annota+ons here
RubyKaigi 2015 14
Slide 15
Slide 15 text
RECAP
• Type = Group of values
• Sta3c typing
• Check type errors
• Op3miza3on
• Don't want to write type annota3ons
=> Type Inference
RubyKaigi 2015 15
Slide 16
Slide 16 text
Various "Type Inference"
• C#:
• var ary = [1,2,3];
• Haskell, OCaml:
• Can omit type of func8on arguments, etc.
• Hindley-Milner type system
RubyKaigi 2015 16
Slide 17
Slide 17 text
2. Hindley-Milner type system
RubyKaigi 2015 17
Slide 18
Slide 18 text
What is "type system"?
• System of types, of course :-)
• Set of rules about type
• Decides which type an expression will have
• Decides which types are compa>ble
• eg. Inheritance
• Every language has its own type system
RubyKaigi 2015 18
Slide 19
Slide 19 text
What is "type system"?
• Hindley-Milner type system
• Haskell = HM + type class + ...
• OCaml = HM + variant + ...
• OreScript = HM (slightly modified)
• Has an algorithm to reconstruct types
• without any type annotaCon(!)
RubyKaigi 2015 19
Slide 20
Slide 20 text
OreScript language spec
• Literal
• eg. 99, true, false
• Anonymous func6on
• eg. fn(x){ x }
• Variable defini6on
• eg. x = 1
• eg. f = fn(x){ x }
• (Note: You can't reassign variables)
• Func6on call
• eg. f(3)
RubyKaigi 2015 20
Slide 21
Slide 21 text
Only unary func+on is supported
• Don't worry, you can emulate binary func5on
f = fn(x, y){ ... }
f(1, 2)
ɹɹ↓
f = fn(x){ fn(y){ ... } }
f(1)(2)
RubyKaigi 2015 21
Slide 22
Slide 22 text
Type system of OreScript
• is any one of ...
• Bool
• Number
• →
• eg. is_odd :: Number → Bool
• Checks
• Type of a and x must be the same
f = fn(a){ ... }
f(x)
RubyKaigi 2015 22
Slide 23
Slide 23 text
Type inference of OreScript
• Given
• f = fn(x){ is_odd(x) }
• is_odd :: Number → Bool
• step1 Assump9on
• f :: (1) → (2)
• x :: (3)
• step2 Equa9ons
• (1) == (3), (3) == Number, (2) == Bool
• step3 Resolve
• (1) == Number, (2) == Bool, (3) == Number
• f :: Number → Bool
RubyKaigi 2015 23
Slide 24
Slide 24 text
RECAP
• Type system = set of rules on types
• Hindley-Minler type system
• Reconstruct types without annota;on
• Assume, Build equa;ons, Resolve
RubyKaigi 2015 24
bin/ore_script
#!/usr/bin/env ruby
require 'ore_script'
# 1. Parse
tree = OreScript::Parser.new.parse(ARGF.read)
p tree
RubyKaigi 2015 32
Slide 33
Slide 33 text
3. OreScript::Evaluator
• Walk the tree and do what is expected
[:if, cond_expr, then_exprs, else_exprs]
def eval_if(env, cond_expr, then_exprs, else_exprs)
cond = eval_expression(env, cond_expr)
case cond
when Value::TRUE
eval_expressions(env, then_exprs)
when Value::FALSE
eval_expressions(env, else_exprs)
else
raise "must not happen"
end
end
RubyKaigi 2015 33
What happens if ...
f = fn(x){ add(x, 1) }
f(true) // !?
• Where's type inference?
• Why we wanted type inference
• "Want to check types without type ano7a8ons"
RubyKaigi 2015 35
Type Inference = Type Check
f = fn(x){ is_odd(x) }
f(true) // !?
• f :: (1) → (2)
x :: (1)
is_odd :: Number → Bool
• Bool == (1)
(1) == Number
(2) == Bool
• ∴ Bool == Number /
/ !?
RubyKaigi 2015 37
Slide 38
Slide 38 text
Type Inference = Type Check
• Infer type before execu0ng program
• If program has an error:
• Bool == Number (unsa0sfiable)
• Otherwise:
• The program has consistent types
(No contradic0on detected)
RubyKaigi 2015 38
Slide 39
Slide 39 text
RECAP
• bin/ore_script
• 1. Parse
• 2. Type check (= Type inference)
• 3. Execute
RubyKaigi 2015 39
Slide 40
Slide 40 text
Implementa)on of type inference
RubyKaigi 2015 40
Slide 41
Slide 41 text
Three classes for type
• Type::TyRaw
• A type already known (Number, Bool, etc.)
• 99 :: #
• Type::TyFun
• Func>on type
• f :: # -> #>
• Type::TyVar
• A type not yet known
• x :: #
• f :: #
RubyKaigi 2015 41
Slide 42
Slide 42 text
Three steps (recap)
1. Assume types
2. Extract type equa3ons
3. Resolve equa3ons
RubyKaigi 2015 42
Slide 43
Slide 43 text
Actual steps
• 1. Assume types
• 2. Extract type equa4ons
• 3. Resolve equa4ons
• 2. Extract type equa4ons
• 3. Resolve equa4ons
• ...
RubyKaigi 2015 43
TypeCheck.unify(*equations)
• Pop one from equations
• # ty2> == # ty4>
• ty1 == ty3
• ty2 == ty4
• # == #
• just ignore
• # == #
• Add (1) == "Number" to the answers
• Replace (1) with # in rest of the equations
• Repeat un?l all equa?ons are removed
RubyKaigi 2015 46
Slide 47
Slide 47 text
Further topics
RubyKaigi 2015 47
Slide 48
Slide 48 text
Downside of sta-c type check
• May reject "valid" program
id = fn(x){ x }
id(99) //→ 99
id(true) //→ true??
RubyKaigi 2015 48
Slide 49
Slide 49 text
let
let id = fn(x){ x } in
id(99)
id(true)
RubyKaigi 2015 49
Slide 50
Slide 50 text
let-poly branch2
id = fn(x){ x } // id :: ∀(1). (1) → (1)
id(99)
id(true)
2 h$ps:/
/github.com/yhara/rk2015orescript/tree/let-poly
RubyKaigi 2015 50
Slide 51
Slide 51 text
let-poly branch2
id = fn(x){ x } // id :: ∀(1). (1) → (1)
id(99) // ←id here :: (2) → (2)
id(true) // ←id here :: (3) → (3)
2 h$ps:/
/github.com/yhara/rk2015orescript/tree/let-poly
RubyKaigi 2015 51
Slide 52
Slide 52 text
Acknowledgements
• ʰTypes And Programming Languageʱ(TAPL)
• Japanese edi7on: ʰܕγεςϜೖʱ
• ʰϓϩάϥϛϯάݴޠͷجૅ֓೦ʱ
• see also(PDF)
• ʰϓϩάϥϛϯάݴޠͷجૅཧʱ(ઈ൛)
• ʰΞϧΰϦζϜWೖʱ (ಉਓࢽ)
• ʰScala By Exampleʱchapter16
• Ibis (Type infrence wriJen in JavaScript)
RubyKaigi 2015 52
Slide 53
Slide 53 text
Summary
• OreScript
• Small language with type inference
• Type check without type annota8on
• Type inference (= type check)
• Build type equea8ons
• Resolve type equea8ons
• hBps:/
/github.com/yhara/rk2015orescript
RubyKaigi 2015 53