Upgrade to Pro — share decks privately, control downloads, hide ads and more …

型で数を表そう

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.
Avatar for xorphitus xorphitus
February 16, 2016

 型で数を表そう

Haskell の型システムを学びました。

Avatar for xorphitus

xorphitus

February 16, 2016
Tweet

More Decks by xorphitus

Other Decks in Programming

Transcript

  1. 今回の動機とか • いい加減 Haskell の勉強しないとやばい • まずは型から • もし再帰的な型定義ができるなら、型で数そのものを表せるんじゃね? •

    で、ググったらいろいろ出てきた 基礎的な話かも知れん あるいは、Haskell 的に的外れだったらごめん
  2. 再帰型があれば自然数を表せる ググるとよく出てくる: ペアノの公理 data Nat = Zero | Succ Nat

    • 0 … Zero • 1 … Succ(Zero) • 2 … Succ(Succ(Zero)) チャーチ数みたい 型で自然数を表現するとこうなるっぽいが Haskell 素人的にはこれを値の世界に持っていきたくなるわけで
  3. 自然数型と値の相互変換 data Nat = Zero | Succ Nat deriving (Show)

    fromPeano Zero = 0 fromPeano (Succ x) = 1 + fromPeano x toPeano 0 = Zero toPeano x = Succ (toPeano (x - 1)) GHCi で動かしてみるよ (一度ファイルに保存してそれを ghci で開かないとエラーになったぞ??)
  4. 自然数型のまま四則演算してみよう なんかもう、やりたいことそのまんまの公式ページがあった (商算はナシ) https://wiki.haskell.org/Peano_numbers add :: Nat -> Nat ->

    Nat add Zero y = y add (Succ x) y = Succ (add x y) この辺の 再帰 + パターンマッチ が全然パっと思い浮かばない 修行不足っぷりに泣けてくる… 公式にもある程のありふれっぷりだが、GHCi で add してみよう
  5. これでどうだ data Nat a = Zero | Succ a deriving

    Show んで、Succ して型を調べてみると :t Succ (Succ Zero) Succ (Succ Zero) :: N (N (N a)) -- その結果がこれだよ 型そのものが入れ子になった → 自然数の値に対応した数だけ、型がネストする! 入れ子が1つ冗長な気もするが…まあ計画通り
  6. 少し調子に乗ってみる data Nat a = Zero | Succ a deriving

    Show type One a = Nat (Nat a) type Two a = Nat (Nat (Nat a)) 型検査により、1 と 1 を受け取って 2 を返すことしかできない愚かな関数 addStupidly :: One a -> One a -> Two a addStupidly (Succ (Succ x)) _ = Succ (Succ (Succ x))
  7. 型的に 1 しか受け取れない関数を実行 2 以上を受け取るとエラーになるよ! *Main> addStupidly (Succ (Succ 0))

    (Succ (Succ 0)) Succ (Succ (Succ 0)) *Main> addStupidly (Succ (Succ (Succ 0))) (Succ (Succ 0)) <interactive>:4:1: Non type-variable argument in the constraint: Num (Nat a) (Use FlexibleContexts to permit this) When checking that ‘it’ has the inferred type it :: forall a. (Num a, Num (Nat a)) => Two (Nat a)