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

型で数を表そう

xorphitus
February 16, 2016

 型で数を表そう

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

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)