SlideShare a Scribd company logo
1 of 72
How wonderful
to be (statically) typed
∼(静的に)型がつくってスバラシイ∼
         石井 大海
自己紹介
•   石井 大海 (id:mr_konn / @mr_konn)

•   早稲田大学数学科三年

    •   集合論や論理学、圏論に興味

•   2010 Summer Intern から PFI でバイト中

•   Haskell Lover
    •   Haskell でウェブ開発などしている
本日のお題:型
• 型がつくと何が嬉しいのか?
• 型・・・むずかしそう
 • ムツカシイ理論ではなく応用例の紹介
 • Haskell の布教ではない
   • 静的型付けの布教です。
Table of Contents
•   型とは何か?──型付け、型推論、型安全

•   wonderful な型たち──型の表現力と応用

    •   いいとこ取り多相──型クラス

    •   型レベル函数:型族──キャスト、Map共通化など

    •   そっちは残像だ──幽霊型はタグ

    •   洒落た多相の使い方──多相型でリーク防止

    •   Haskell、昇進す。──Data Kinds

•   その型、強力につき──依存型と証明
Table of Contents
•   型とは何か?──型付け、型推論、型安全

•   wonderful な型たち──型の表現力と応用

    •   いいとこ取り多相──型クラス

    •   型レベル函数:型族──キャスト、Map共通化など

    •   そっちは残像だ──幽霊型はタグ

    •   洒落た多相の使い方──多相型でリーク防止

    •   Haskell、昇進す。──Data Kinds

•   その型、強力につき──依存型と証明
型とは何か?
──型付け、型推論、型安全──
型とは何か?
“データ型(でーたがた、data type)とは、コ
ンピュータにおけるデータの扱いに関する形
式のことである。データタイプとも。データ
型は、プログラミングなどにおいて変数その
ものや、その中に代入されるオブジェクトや
値が対象となる。”

              ── データ型 - Wikipedia
型とは何か?
•   つまり?

    •   値の種類を区別するタグのようなもの

•   世の言語は大きく「型付き言語」と「型無
    し言語」に大別出来る

    •   型付き・・・C, Ruby, Haskell, LISP, Smalltalk...

    •   型無し・・・Brainf*ck, Lazy-K, ...
型なし……?
•   実用的なプログラミング言語は全部型がついてる気が
    する。

    •   Tcl :すべては文字列。でも実際には型別の内部表現
        を持っている(らしい)。

•   そもそもの untyped・・・Untyped Lambda Calculus

•   型あり言語の分類

    •   動的型付け・・・LISP, Ruby, Smalltalk, JavaScript...

    •   静的型付け・・・Java, C, Haskell, OCaml, ...
型なし vs. 動的型
動的と静的の違い
•   動的型付け

    •   型検査は実行時に行われる

        •   (compile-time) untyped と云える?

        •   以後「型なし」は「動的型付け」の alias とする

    •   インタプリタ言語はこれが多い

•   静的型付け

    •   型検査はコンパイル時に行われる

    •   型が合わないものは実行する前に弾かれる
型検査
• 演算の値の型が合っているか検査
• 合っていなかったら?
 • 言語によって弾いたり、キャストした
  りする。

→ 型安全性
型安全性?
•   ナイーヴな定義:「型検査を通ったものが変な挙
    動をしない」

•   ちょっと厳密な定義

    •   Preservation: 型が評価の順番に依らない

    •   Progress: 型が付いたら「刺さらない」

        •   「刺さらない」ってなんや(意味論による)
型安全性と言語
•   Haskell……型安全と云ってよい

    •   黒魔術を使わなければ型安全

    •   停止性を込めると型安全じゃない

        •   f x = f (f x) みたいなコードも型は付くが停止し
            ない

•   C……型安全じゃない!

    •   cast や printf(“%s”, 12); などあぶない
型推論
•   函数の型を自動的に推論してくれる機能

•   型推論なし・・・C, Java, ...

•   型推論あり・・・Haskell, Scala, OCaml, ...

    •   健全性とか完全性とか色々概念があるらしいです
        がぶっちゃけよくわからない

    •   色んな強さの型推論がある、と云うことで。

    •   コンパイラが付けられない部分は手で注釈
ここからは
• 静的型付け、型推論あり言語の布教
• かつある程度の型安全性を持つ言語
 • Preserve は当然仮定
 • 停止しないくらいは許す
   • SEGV ったりしない、程度。
その前に……なぜ型?
• 型はドキュメント
 • 型を見れば(ある程度)挙動がわかる
   • 勿論 Int → Int とか見せられてもわか
    らない ^^;(でも無いよりマシ)

• 型検査通ればある程度正しく動く
 • どの程度?→型の表現力による!
型はドキュメント
•   SMTP 通信用の型

•   複数値を取るリスト型や、値を取らないかも
    しれない Maybe 型などが雄弁に語る

    data SMTPCommand =   HELO   ByteString
                     |   EHLO   ByteString
                     |   MAIL   Path [(ByteString, ByteString)]
                     |   RCPT   Path [(ByteString, ByteString)]
                     |   DATA   ByteString
                     |   RSET
                     |   VRFY   ByteString
                     |   EXPN   ByteString
                     |   HELP   (Maybe ByteString)
                     |   NOOP   (Maybe ByteString)
                     |   QUIT

    data Path = Path [ByteString] Mailbox
              | Empty
型はドキュメント
•   各 ByteString が何を指すのかわからない……

    •   型に別名を付けるとわかりやすい!

    •   中身としては同じ。見通しはよくなる
    type Domain = ByteString
    type Param = (ByteString, ByteString)
    data SMTPCommand = HELO Domain
                     | EHLO Domain
                     | MAIL Path [Param]
                     | RCPT Path [Param]
                     | DATA ByteString
                     | RSET
                     | VRFY ByteString
                     | EXPN ByteString
                     | HELP (Maybe ByteString)
                     | NOOP (Maybe ByteString)
                     | QUIT

    data Path = Path [Domain] Mailbox
              | Empty
wonderful な型たち
  ──型の表現力と応用──
型クラス
•   Ad-hoc 多相を実現する機構

    •   複数の型に共通な演算をオーバーロード

    •   cf. Parametric 多相:共通の「実装」を共有する

•   代替手法

    •   強力なモジュールシステム(like Alloy, Agda,
        OCaml, ...)

    •   プリプロセッサ(camlp4?)
数値型クラス
         class (Eq a, Show a) => Num a where
             (+), (-), (*)       :: a -> a -> a
             negate              :: a -> a
             abs                 :: a -> a
             signum              :: a -> a
             fromInteger         :: Integer -> a
             x - y               = x + negate y
             negate x            = 0 - x



•   数値としての特徴を持つ型のクラス

•   加減乗除、反転、絶対値、数字からの変換など

•   Num である為には Eq, Show でもある必要がある

    •   型クラスは、型への「制約」「述語」として考えられる
ファンクタ型クラス
         class Functor f where
           fmap :: (a -> b) -> f a -> f b



•   普通の函数を「持ち上げ」られるコンテナのよう
    なもの

    •   []、Maybe、IO などなど

•   Maybe a は値を持つが、 Maybe は値を持たない

    •   Maybe :: * → * :型を受けとって型を返す「函
        数」みたいなもの
多引数型クラスの例
        class Monad m => MonadState s m | m -> s where
            get :: m s
            get = state (s -> (s, s))
            put :: s -> m ()
            put s = state (_ -> ((), s))
            state :: (s -> (a, s)) -> m a
            state f = do
              s <- get
              let ~(a, s) = f s
              put s
              return a


•   「m は内部状態 s を持つモナド」

    •   (モナド=すごいコンテナ)

•   m を決めると s が決まる:「m → s」関数従属性
型クラス:まとめ

• 型の述語のようなもの
• Ad-hoc 多相を綺麗に実現する
• 函数従属性で依存関係を記述出来る
型族

• 型レベル函数のようなもの
• 型別名を付けるものと、データを新た
 に定義するもの

• 型クラスに付随する型族
例1: MonadStateの書き換え
      class Monad m => MonadState m where
          type State m :: *
          get :: m (State m)
          get = state (s -> (s, s))
          put :: State m -> m ()
          put s = state (_ -> ((), s))
          state :: (State m -> (a, State m)) -> m a
          state f = do
            s <- get
            let ~(a, s) = f s
            put s
            return a



•   State m が今までの s

•   型名がドキュメントの役割を果している

•   複雑なFunDepsを無くし、かつ一引数クラスで書ける
例2:演算キャスト
    class Add a b where
      type SumType a b
      add :: a -> b -> SumType a b

    instance Add Int Int where
      type SumType Int Int = Int
      add = (+)

    instance Add Int Double where
      type SumType Int Double = Double
      a `add` b = fromIntegral a + b




• 二つの型の足し算を定義
• SumType はキャストされた結果の型
例3:マップの一般化
   lass Key k where
     data Map k :: * -> *
     empty :: Map k v
     lookup :: k -> Map k v -> Maybe v
     insert :: k -> v -> Map k v -> Map k v

   instance Key Int where
     newtype Map Int a   =   IMap (IM.IntMap a)
     empty               =   IMap IM.empty
     lookup k (IMap d)   =   IM.lookup k d
     insert k v (IMap d) =   IMap $ IM.insert k v d

   instance Key ByteString where
     newtype Map ByteString a = BSMap (Trie a)

   instance (Key a, Key b) => Key (a, b) where
     newtype Map (a, b) v = TMap (Map a (Map b v))




• 辞書構造をキーの型によって使いわけ
洒落た多相の使い方
•   いままでの多相型の使い方

    •   ad-hoc
        •   複数の型に共通な操作を抽象化。

        •   Num, Functor, Monad,...
    •   parametric
        •   中身を抽象化したコンテナなど

        •   リスト, Map, a → a, ...
残像だ──幽霊型
• 幽霊型(phantom types)
 • 実際のデータ定義に出て来ない型引数
  を取る型

• データにタグを付けることが出来る
• GADTs と云う機構を使って制御出来る
例:構文木
• 型付き言語の構文木を書きたい
 data Expr = Zero | Succ Expr  | Plus Expr Expr
           | Yes | No | IsZero | Apply Expr Expr

 eval   :: Expr -> Expr
 eval   Zero       = Zero
 eval   (Succ a)   = Succ $ eval a
 eval   (Plus a (eval -> Zero))   = eval a
 eval   (Plus a (eval -> Succ b)) = Succ $ eval $ Plus a b
 eval   Yes = Yes
 eval   No = No
 eval   (Apply IsZero (eval -> Zero)) = Yes
 eval   (Apply IsZero _) = No
 eval   IsZero = IsZero
 eval   _ = error "type error"
実行例
    ghci> eval (Plus Zero (Succ (Succ Zero)))
    Succ (Succ Zero)
    ghci> eval (Plus (Succ Zero) (Succ (Succ Zero)))
    Succ (Succ (Succ Zero))
    ghci> eval (Apply IsZero (Succ Zero))
    No
    ghci> eval (Apply IsZero (Plus Zero Zero))
    Yes
    ghci> eval (Plus Yes Zero)
    Yes
    ghci> eval (Apply IsZero (Succ Yes))
    No
    ghci> eval (Plus Zero Yes)
    *** Exception: type error

•   型があわないのが実行時エラーになる

•   素朴にやるとエラーが……。一々チェック?
型チェック通ったら
落ちて欲しくない…
処理系に
やらせましょう。
例:型付き構文木
        data Expr a   where
          Zero   ::   Expr Int
          Succ   ::   Expr Int -> Expr Int
          Plus   ::   Expr Int -> Expr Int -> Expr Int
          Yes    ::   Expr Bool
          No     ::   Expr Bool
          IsZero ::   Expr (Int -> Bool)
          Apply ::    Expr (a -> b) -> Expr a -> Expr b

        eval   :: Expr a -> Expr a
        eval   (Succ a)                  = Succ (eval a)
        eval   (Plus a b)   = eval a
        eval   (Plus a (eval -> Succ b)) = Succ (eval $ Plus a b)
        eval   (Apply IsZero (eval -> Zero))   = Yes
        eval   (Apply IsZero (eval -> Succ _)) = No
        eval   a = a



•   各コンストラクタに型が付加されている

    •    変な構文木を弾いてくれる!
型引数、
更には幽霊型の威力
型引数の威力
• 型引数は「階層の区別」に使える
 • タグとしての型引数
• 「ランク2多相」と組み合わせると、安
 全なメモリアクセスやリソース管理に
 使える
Rank 2 多相?

• 多相函数を引数に取れる型拡張
 • Haskell の総称プログラミングライブ
  ラリSYBなどにも使われる

 • ここではちょっと違った例を見ます。
ST Monad

• State thread: メモリを用いた高速な状態
 更新をするための機構

• Haskell は pure なので外に inpure な操作
 が漏れないようにしたい
ST Monad
data ST s a
-- 内部状態 s を持ち、a の値を返す演算。
data STRef s a
-- 内部状態 s を持ち、a の値を保持する可変値。
-- これも s を漏らしてはいけない。

newSTRef :: a -> ST s (STRef s a)
-- 新しい STRef を作る。その際 ST と STRef の内部状態は統一する。

readSTRef :: STRef s a -> ST s a
writeSTRef :: STRef s a -> a -> ST s ()
modifySTRef :: STRef s a -> (a -> a) -> ST s ()
-- STRef を読み書きするための函数。ST内部でしか使えない。

runST :: (forall s. ST s a) -> a
-- ST 演算を実行して、結果を返す函数。
-- 内部状態は捨てられるので純粋性は保たれる。
利用例
    f str = do
      ref <- newSTRef str
      modifySTRef ref (++ ", that is the value")
      readSTRef ref

    main :: IO ()
    main = do
      print $ runST $ f "hoge"



• 簡単な例
• 破壊的代入を行えるので、STArray など
 高速な配列演算を行うための型もある

• Bloom Filter の実装などにも使われる
外部に漏れない?
 leaker str = do
   ref <- newSTRef str
   modifySTRef ref (++ ", that is the value")
   return ref

 main :: IO ()
 main = do
   let ref = runST $ leaker "hoge"
   print $ runST $ anotherEvilSToperation ref



• STRef を外に返すような函数を書けば漏
 れるんじゃないの?
コンパイルしてみる
        /Users/hiromi/pfi/seminar-20120411/test01.lhs:121:11:
           Couldn't match type `a0' with `STRef s [Char]'
             because type variable `s' would escape its scope
          This (rigid, skolem) type variable is bound by
             a type expected by the context: ST s a0
           In the second argument of `($)', namely `leaker "hoge"'
           In the second argument of `($)', namely `runST $ leaker "hoge"'
           In the expression: print $ runST $ leaker "hoge"
        Failed, modules loaded: none.


•   STRef s [Char] の s は ST の内部状態と同じ

•   s は runST :: (forall s. ST s a) → a の引数内側で束縛

    •     何でもいい、だからこそ何だかわからない!
ちょっと理由説明
•   runST :: (forall s. ST s (STRef s a))
     → forall s. STRef s a
    •   と云う型じゃだめなの?

•   束縛変数の記号を変えてもいいので……

•   (forall s’. ST s’ (STRef s’ a)) → forall s. STRef s a
    •   と書き換えることも出来て、型があわない
さらに応用:リソース管理
•   問題:Handle など scarce なリソースはすぐに解放した
    い

    •   リソース取得と解放とが同順とは限らない

    •   解放したリソースを外でアクセス出来ないようにし
        たい

•   「リージョン」を使う!

    •   同一リージョン中は割り当てたリソースが使用可
        能、抜けると解放しアクセス不可能に
実装方針
• ST を真似て Rank 2 多相で leak を防ぐ
 • 内部状態ではなくただのタグ、幽霊型
• 同順じゃなく解放するには?
 • リージョンをネスト
 • 型クラス+モナド変換子で親リージョ
  ンのリソースを割り当てられるように
実装
newtype RIO s a = RIO (ReaderT (IORef [Handle]) IO a)
    deriving (Functor, Monad, MonadReader (IORef [Handle]))
newtype RHandle s = RHandle Handle
runRIO :: (forall s. RIO s a) -> IO a
runRIO (RIO act) = bracket (newIORef []) (readIORef >=> mapM_ hClose) $
  runReaderT act

openFileR :: FilePath -> IOMode -> RIO s (RHandle s)
openFileR fp mode = do
  h <- RIO $ liftIO $ openFile fp mode
  RIO $ ReaderT $ ref -> liftIO $ modifyIORef ref (h:)
  return (RHandle h)



   •   開いたハンドルへの参照を持っておく

   •   終了時に解放するようにする

       •   ハンドルは全てRHandle の形で扱い、閉じれない
使ってみる
  test = do
    h <- openFileR "conf.txt" ReadMode
    str <- hGetLineR h
    putStrLnR str

  main = runRIO test



• 型は省略しても推論してくれる(!!)
• 上の実装だと一リージョンしか扱えな
 いが、型クラスによってネスト出来る
やりたい例
        RIO s IO
        RIO t (RIO s IO)
やりたい例
1   ファイル1を開く   h1 :: RHandle s   RIO s IO
                                 RIO t (RIO s IO)
やりたい例
1   ファイル1を開く   h1 :: RHandle s   RIO s IO
                                 RIO t (RIO s IO)
やりたい例
      1   ファイル1を開く   h1 :: RHandle s   RIO s IO
                                       RIO t (RIO s IO)


 h1        2   設定ファイルを開く
を渡す
やりたい例
      1   ファイル1を開く   h1 :: RHandle s           RIO s IO
                                               RIO t (RIO s IO)


 h1        2   設定ファイルを開く
                                       h2, hc :: RHandle t
を渡す
           3   ファイル2の位置を読み、開く
やりたい例
      1   ファイル1を開く   h1 :: RHandle s           RIO s IO
                                               RIO t (RIO s IO)


 h1        2   設定ファイルを開く
                                       h2, hc :: RHandle t
を渡す
           3   ファイル2の位置を読み、開く

           4   ファイル3を(親リージョンで)開く                  h3 :: RHandle s
やりたい例
      1   ファイル1を開く    h1 :: RHandle s           RIO s IO
                                                RIO t (RIO s IO)


 h1        2   設定ファイルを開く
                                        h2, hc :: RHandle t
を渡す
           3   ファイル2の位置を読み、開く

           4   ファイル3を(親リージョンで)開く                   h3 :: RHandle s

           5   1, 2の内容を交互に3へ書き込む
やりたい例
      1   ファイル1を開く       h1 :: RHandle s           RIO s IO
                                                   RIO t (RIO s IO)


 h1        2   設定ファイルを開く
                                           h2, hc :: RHandle t
を渡す
           3   ファイル2の位置を読み、開く

           4   ファイル3を(親リージョンで)開く                      h3 :: RHandle s

           5   1, 2の内容を交互に3へ書き込む
                     h2, hc を解放
               h3 を返す; h3は型があうので返せる
やりたい例
      1   ファイル1を開く       h1 :: RHandle s           RIO s IO
                                                   RIO t (RIO s IO)


 h1        2   設定ファイルを開く
                                           h2, hc :: RHandle t
を渡す
           3   ファイル2の位置を読み、開く

           4   ファイル3を(親リージョンで)開く                      h3 :: RHandle s

           5   1, 2の内容を交互に3へ書き込む
                     h2, hc を解放
               h3 を返す; h3は型があうので返せる
      6   1 に残りがあれば それを 3へ書き込む
やりたい例
      1   ファイル1を開く         h1 :: RHandle s           RIO s IO
                                                     RIO t (RIO s IO)


 h1        2   設定ファイルを開く
                                             h2, hc :: RHandle t
を渡す
           3   ファイル2の位置を読み、開く

           4   ファイル3を(親リージョンで)開く                        h3 :: RHandle s

           5   1, 2の内容を交互に3へ書き込む
                       h2, hc を解放
               h3 を返す; h3は型があうので返せる
      6   1 に残りがあれば それを 3へ書き込む

          h3, h1 を解放
そのまま書ける
test3 = runSIO $ do
  h1 <- newSHandle "/tmp/SafeHandles.hs" ReadMode
  h3 <- newRgn (test3_internal h1)
  till (shIsEOF h1) (shGetLine h1 >>= shPutStrLn h3)
  shReport "test3 done"

test3_internal h1 = do
  h2 <- newSHandle "/tmp/ex-file.conf" ReadMode
  fname <- shGetLine h2
  h3 <- liftSIO (newSHandle fname WriteMode)
  shPutStrLn h3 fname
  till (liftM2 (||) (shIsEOF h2) (shIsEOF h1))
    (shGetLine h2 >>= shPutStrLn h3 >> shGetLine h1 >>= shPutStrLn h3)
  shReport "Finished zipping h1 and h2"
  return h3



 •   ネストしても推論してくれる!

     •   勝手にタグがつく!

 •   リソースの受け渡しも型が監視してくれる!
幽霊型・Rank 2多相
     他の応用例

• セッション型
 • ネットワーク/スレッド通信のチャネ
  ルの「使われ方」の不整合を型が検
  出してくれる
Session 型の例
typecheck1 $ c -> send c "abc"
  :: (Length ss l) => Session t (ss :> Send [Char] a) (ss :> a) ()
                                                   example from [10]


     • 操作が 型レベルリストで並んでいる
       • Session t (事前条件) (事後条件) 結果
       • 上の例は「一度だけ、一つだけチャネ
           ルを使って文字列をを送る」と読む

       • t は Rank 2 多相によるリーク防止
昇進──Data Kinds

• Data Kinds?
 • データ型を型レベルへ「持ち上げ」
 • GADTs や Type Family などと組み合わ
   せて強力な威力を発揮する
例:長さ付きリスト
• 幽霊型として、長さをパラメタ化
• 空リストへの先頭要素、tail アクセスを
 防止

• 連結の際は型レベル足し算がいる
 • type family で足せばいい!
実装例
data Nat = Z | S Nat

data Vector :: Nat -> * -> * where
  Nil :: Vector Z a
  Cons :: a -> Vector n a -> Vector (S n) a

vhead :: Vector (S n) a -> a
vhead (Cons a _) = a

vtail :: Vector (S n) a -> Vector n a
vtail (Cons _ as) = as

vnull :: Vector n a -> Bool
vnull Nil = True
vnull _   = False

type family (a :: Nat) :+: (b :: Nat) :: Nat
type instance Z :+: a = a
type instance S n :+: a = S (n :+: a)

vappend :: Vector n a -> Vector m a -> Vector (n :+: m) a
vappend Nil v         = v
vappend (Cons a as) v = Cons a (as `vappend` v)
以前は…。
• Nat を型に持ち上げられなかったので
 無意味な足し算が定義出来る可能性が
 あった

• 同様に長さ以外のインデックスが付く
 可能性があった

• 持ち上げる事で範囲を制限!
補足
•   Data Kinds が強力になり、型が引数として任
    意の値を取れるようになる(!!)

    •   依存型と云う

    •   Coq, Agda など

•   Curry-Howard 対応

    •   型と論理式の対応→定理証明
時間切れ orz
References
1.   “Fun with type functions”, Oleg Kiselyov, Simon Peyton Jones and Chung-chieh
     Shan, 2010
2.   “Giving Haskell a Promotion”,B. A.Yorgey, S. Weirich, J. Cretin, Simon Peyton
     Jones and D.Vytiniotis, 2011
3.   “Lightweight Monadic Regions”, Oleg Kiselyov, Chung-chieh Shan, 2008
4.   “Algebra of Programming in Agda”, Shin-Cheng Mu, Hsiang-Shang Ko, Patrik
     Jansson, 2009
5.   “Yesod Web Framework for Haskell”
6.   “データ型 - Wikipedia”, Wikipedia

7.   “Type safety - Wikipedia”, Wikipedia
8.   “Phantom type - HaskellWiki”, HaskellWiki
9.   “Region-based resource management”, Oleg Kiselyov, 2011
10. “full-sessions-0.6.1”, id:keigoi
11. “プログラミングCoq”, 池渕未来
Any Questions?
御清聴
ありがとうございました

More Related Content

What's hot

C++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるC++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるHideyuki Tanaka
 
あなたのScalaを爆速にする7つの方法(日本語版)
あなたのScalaを爆速にする7つの方法(日本語版)あなたのScalaを爆速にする7つの方法(日本語版)
あなたのScalaを爆速にする7つの方法(日本語版)x1 ichi
 
たのしい高階関数
たのしい高階関数たのしい高階関数
たのしい高階関数Shinichi Kozake
 
IdrisでWebアプリを書く
IdrisでWebアプリを書くIdrisでWebアプリを書く
IdrisでWebアプリを書くHideyuki Tanaka
 
(Lambdaだけで) 純LISPのような ナニかを作る
(Lambdaだけで)純LISPのようなナニかを作る(Lambdaだけで)純LISPのようなナニかを作る
(Lambdaだけで) 純LISPのような ナニかを作るDaichi Teruya
 
はてなブックマーク in Scala
はてなブックマーク in Scalaはてなブックマーク in Scala
はてなブックマーク in ScalaLintaro Ina
 
JavaScriptクイックスタート
JavaScriptクイックスタートJavaScriptクイックスタート
JavaScriptクイックスタートShumpei Shiraishi
 
Haskell勉強会 in ie
Haskell勉強会 in ieHaskell勉強会 in ie
Haskell勉強会 in iemaeken2010
 
これから Haskell を書くにあたって
これから Haskell を書くにあたってこれから Haskell を書くにあたって
これから Haskell を書くにあたってTsuyoshi Matsudate
 
Scalaで型クラス入門
Scalaで型クラス入門Scalaで型クラス入門
Scalaで型クラス入門Makoto Fukuhara
 
実務者のためのかんたんScalaz
実務者のためのかんたんScalaz実務者のためのかんたんScalaz
実務者のためのかんたんScalazTomoharu ASAMI
 
Scalaで萌える関数型プログラミング[完全版]
Scalaで萌える関数型プログラミング[完全版]Scalaで萌える関数型プログラミング[完全版]
Scalaで萌える関数型プログラミング[完全版]Ra Zon
 
Scala の関数型プログラミングを支える技術
Scala の関数型プログラミングを支える技術Scala の関数型プログラミングを支える技術
Scala の関数型プログラミングを支える技術Naoki Aoyama
 
15分でざっくり分かるScala入門
15分でざっくり分かるScala入門15分でざっくり分かるScala入門
15分でざっくり分かるScala入門SatoYu1ro
 
(define)なしで再帰関数を定義する
(define)なしで再帰関数を定義する(define)なしで再帰関数を定義する
(define)なしで再帰関数を定義するblackenedgold
 
Material
MaterialMaterial
Material_TUNE_
 
BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdfHiroshi Ono
 

What's hot (20)

C++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるC++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISる
 
あなたのScalaを爆速にする7つの方法(日本語版)
あなたのScalaを爆速にする7つの方法(日本語版)あなたのScalaを爆速にする7つの方法(日本語版)
あなたのScalaを爆速にする7つの方法(日本語版)
 
たのしい高階関数
たのしい高階関数たのしい高階関数
たのしい高階関数
 
Thinking in Cats
Thinking in CatsThinking in Cats
Thinking in Cats
 
IdrisでWebアプリを書く
IdrisでWebアプリを書くIdrisでWebアプリを書く
IdrisでWebアプリを書く
 
(Lambdaだけで) 純LISPのような ナニかを作る
(Lambdaだけで)純LISPのようなナニかを作る(Lambdaだけで)純LISPのようなナニかを作る
(Lambdaだけで) 純LISPのような ナニかを作る
 
はてなブックマーク in Scala
はてなブックマーク in Scalaはてなブックマーク in Scala
はてなブックマーク in Scala
 
JavaScriptクイックスタート
JavaScriptクイックスタートJavaScriptクイックスタート
JavaScriptクイックスタート
 
Haskell勉強会 in ie
Haskell勉強会 in ieHaskell勉強会 in ie
Haskell勉強会 in ie
 
これから Haskell を書くにあたって
これから Haskell を書くにあたってこれから Haskell を書くにあたって
これから Haskell を書くにあたって
 
Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7
 
Scalaで型クラス入門
Scalaで型クラス入門Scalaで型クラス入門
Scalaで型クラス入門
 
実務者のためのかんたんScalaz
実務者のためのかんたんScalaz実務者のためのかんたんScalaz
実務者のためのかんたんScalaz
 
Scalaで萌える関数型プログラミング[完全版]
Scalaで萌える関数型プログラミング[完全版]Scalaで萌える関数型プログラミング[完全版]
Scalaで萌える関数型プログラミング[完全版]
 
Scala の関数型プログラミングを支える技術
Scala の関数型プログラミングを支える技術Scala の関数型プログラミングを支える技術
Scala の関数型プログラミングを支える技術
 
たのしい関数型
たのしい関数型たのしい関数型
たのしい関数型
 
15分でざっくり分かるScala入門
15分でざっくり分かるScala入門15分でざっくり分かるScala入門
15分でざっくり分かるScala入門
 
(define)なしで再帰関数を定義する
(define)なしで再帰関数を定義する(define)なしで再帰関数を定義する
(define)なしで再帰関数を定義する
 
Material
MaterialMaterial
Material
 
BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdf
 

Viewers also liked

実践・完全犯罪のつくり方
実践・完全犯罪のつくり方実践・完全犯罪のつくり方
実践・完全犯罪のつくり方Hiromi Ishii
 
Yesod でブログエンジンをつくってみた
Yesod でブログエンジンをつくってみたYesod でブログエンジンをつくってみた
Yesod でブログエンジンをつくってみたHiromi Ishii
 
Lebesgue 可測性に関する Solovay-Shelah の結果に必要な記述集合論のごく基本的な事項
Lebesgue 可測性に関する Solovay-Shelah の結果に必要な記述集合論のごく基本的な事項Lebesgue 可測性に関する Solovay-Shelah の結果に必要な記述集合論のごく基本的な事項
Lebesgue 可測性に関する Solovay-Shelah の結果に必要な記述集合論のごく基本的な事項Hiromi Ishii
 
Template Haskell とか
Template Haskell とかTemplate Haskell とか
Template Haskell とかHiromi Ishii
 
実数の集合はどこまで可測になれるか?
実数の集合はどこまで可測になれるか?実数の集合はどこまで可測になれるか?
実数の集合はどこまで可測になれるか?Hiromi Ishii
 
Lebesgue可測性に関するSoloayの定理と実数の集合の正則性
Lebesgue可測性に関するSoloayの定理と実数の集合の正則性Lebesgue可測性に関するSoloayの定理と実数の集合の正則性
Lebesgue可測性に関するSoloayの定理と実数の集合の正則性Hiromi Ishii
 
(数式の入った)本をつくる
(数式の入った)本をつくる(数式の入った)本をつくる
(数式の入った)本をつくるHiromi Ishii
 
Alloy Analyzer のこと
Alloy Analyzer のことAlloy Analyzer のこと
Alloy Analyzer のことHiromi Ishii
 
技術者が知るべき Gröbner 基底
技術者が知るべき Gröbner 基底技術者が知るべき Gröbner 基底
技術者が知るべき Gröbner 基底Hiromi Ishii
 
ものまね鳥を愛でる 結合子論理と計算
ものまね鳥を愛でる 結合子論理と計算ものまね鳥を愛でる 結合子論理と計算
ものまね鳥を愛でる 結合子論理と計算Hiromi Ishii
 
数学プログラムを Haskell で書くべき 6 の理由
数学プログラムを Haskell で書くべき 6 の理由数学プログラムを Haskell で書くべき 6 の理由
数学プログラムを Haskell で書くべき 6 の理由Hiromi Ishii
 
御清聴ありがとうございました
御清聴ありがとうございました御清聴ありがとうございました
御清聴ありがとうございましたHiromi Ishii
 
Ruby を用いた超絶技巧プログラミング(夏のプログラミングシンポジウム 2012)
Ruby を用いた超絶技巧プログラミング(夏のプログラミングシンポジウム 2012)Ruby を用いた超絶技巧プログラミング(夏のプログラミングシンポジウム 2012)
Ruby を用いた超絶技巧プログラミング(夏のプログラミングシンポジウム 2012)mametter
 

Viewers also liked (13)

実践・完全犯罪のつくり方
実践・完全犯罪のつくり方実践・完全犯罪のつくり方
実践・完全犯罪のつくり方
 
Yesod でブログエンジンをつくってみた
Yesod でブログエンジンをつくってみたYesod でブログエンジンをつくってみた
Yesod でブログエンジンをつくってみた
 
Lebesgue 可測性に関する Solovay-Shelah の結果に必要な記述集合論のごく基本的な事項
Lebesgue 可測性に関する Solovay-Shelah の結果に必要な記述集合論のごく基本的な事項Lebesgue 可測性に関する Solovay-Shelah の結果に必要な記述集合論のごく基本的な事項
Lebesgue 可測性に関する Solovay-Shelah の結果に必要な記述集合論のごく基本的な事項
 
Template Haskell とか
Template Haskell とかTemplate Haskell とか
Template Haskell とか
 
実数の集合はどこまで可測になれるか?
実数の集合はどこまで可測になれるか?実数の集合はどこまで可測になれるか?
実数の集合はどこまで可測になれるか?
 
Lebesgue可測性に関するSoloayの定理と実数の集合の正則性
Lebesgue可測性に関するSoloayの定理と実数の集合の正則性Lebesgue可測性に関するSoloayの定理と実数の集合の正則性
Lebesgue可測性に関するSoloayの定理と実数の集合の正則性
 
(数式の入った)本をつくる
(数式の入った)本をつくる(数式の入った)本をつくる
(数式の入った)本をつくる
 
Alloy Analyzer のこと
Alloy Analyzer のことAlloy Analyzer のこと
Alloy Analyzer のこと
 
技術者が知るべき Gröbner 基底
技術者が知るべき Gröbner 基底技術者が知るべき Gröbner 基底
技術者が知るべき Gröbner 基底
 
ものまね鳥を愛でる 結合子論理と計算
ものまね鳥を愛でる 結合子論理と計算ものまね鳥を愛でる 結合子論理と計算
ものまね鳥を愛でる 結合子論理と計算
 
数学プログラムを Haskell で書くべき 6 の理由
数学プログラムを Haskell で書くべき 6 の理由数学プログラムを Haskell で書くべき 6 の理由
数学プログラムを Haskell で書くべき 6 の理由
 
御清聴ありがとうございました
御清聴ありがとうございました御清聴ありがとうございました
御清聴ありがとうございました
 
Ruby を用いた超絶技巧プログラミング(夏のプログラミングシンポジウム 2012)
Ruby を用いた超絶技巧プログラミング(夏のプログラミングシンポジウム 2012)Ruby を用いた超絶技巧プログラミング(夏のプログラミングシンポジウム 2012)
Ruby を用いた超絶技巧プログラミング(夏のプログラミングシンポジウム 2012)
 

Similar to How wonderful to be (statically) typed 〜型が付くってスバラシイ〜

Scalaプログラミング・マニアックス
Scalaプログラミング・マニアックスScalaプログラミング・マニアックス
Scalaプログラミング・マニアックスTomoharu ASAMI
 
オブジェクト指向開発におけるObject-Functional Programming
オブジェクト指向開発におけるObject-Functional Programmingオブジェクト指向開発におけるObject-Functional Programming
オブジェクト指向開発におけるObject-Functional ProgrammingTomoharu ASAMI
 
中3女子でもわかる constexpr
中3女子でもわかる constexpr中3女子でもわかる constexpr
中3女子でもわかる constexprGenya Murakami
 
すごいHaskell読書会 第7章 (前編)
すごいHaskell読書会 第7章 (前編)すごいHaskell読書会 第7章 (前編)
すごいHaskell読書会 第7章 (前編)Suguru Hamazaki
 
リテラル文字列型までの道
リテラル文字列型までの道リテラル文字列型までの道
リテラル文字列型までの道Satoshi Sato
 
JavaScript 講習会 #1
JavaScript 講習会 #1JavaScript 講習会 #1
JavaScript 講習会 #1Susisu
 
Haskell勉強会2 in ie
Haskell勉強会2 in ieHaskell勉強会2 in ie
Haskell勉強会2 in iemaeken2010
 
中3女子が狂える本当に気持ちのいい constexpr
中3女子が狂える本当に気持ちのいい constexpr中3女子が狂える本当に気持ちのいい constexpr
中3女子が狂える本当に気持ちのいい constexprGenya Murakami
 
asm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web gamesasm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web gamesNoritada Shimizu
 
Lisp Tutorial for Pythonista : Day 3
Lisp Tutorial for Pythonista : Day 3Lisp Tutorial for Pythonista : Day 3
Lisp Tutorial for Pythonista : Day 3Ransui Iso
 
Vim scriptとJavaとHaskell
Vim scriptとJavaとHaskellVim scriptとJavaとHaskell
Vim scriptとJavaとHaskellaiya000
 
Ruby 3の型推論やってます
Ruby 3の型推論やってますRuby 3の型推論やってます
Ruby 3の型推論やってますmametter
 
LastaFluteでKotlinをはじめよう
LastaFluteでKotlinをはじめようLastaFluteでKotlinをはじめよう
LastaFluteでKotlinをはじめようShinsuke Sugaya
 
BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdfHiroshi Ono
 
BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdfHiroshi Ono
 
とあるFlashの自動生成
とあるFlashの自動生成とあるFlashの自動生成
とあるFlashの自動生成Akineko Shimizu
 
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8y_taka_23
 
20141128 iOSチーム勉強会 My Sweet Swift
20141128 iOSチーム勉強会 My Sweet Swift20141128 iOSチーム勉強会 My Sweet Swift
20141128 iOSチーム勉強会 My Sweet Swiftnecocen
 

Similar to How wonderful to be (statically) typed 〜型が付くってスバラシイ〜 (20)

Scalaプログラミング・マニアックス
Scalaプログラミング・マニアックスScalaプログラミング・マニアックス
Scalaプログラミング・マニアックス
 
オブジェクト指向開発におけるObject-Functional Programming
オブジェクト指向開発におけるObject-Functional Programmingオブジェクト指向開発におけるObject-Functional Programming
オブジェクト指向開発におけるObject-Functional Programming
 
Phantom Type in Scala
Phantom Type in ScalaPhantom Type in Scala
Phantom Type in Scala
 
中3女子でもわかる constexpr
中3女子でもわかる constexpr中3女子でもわかる constexpr
中3女子でもわかる constexpr
 
すごいHaskell読書会 第7章 (前編)
すごいHaskell読書会 第7章 (前編)すごいHaskell読書会 第7章 (前編)
すごいHaskell読書会 第7章 (前編)
 
リテラル文字列型までの道
リテラル文字列型までの道リテラル文字列型までの道
リテラル文字列型までの道
 
JavaScript 講習会 #1
JavaScript 講習会 #1JavaScript 講習会 #1
JavaScript 講習会 #1
 
Haskell勉強会2 in ie
Haskell勉強会2 in ieHaskell勉強会2 in ie
Haskell勉強会2 in ie
 
中3女子が狂える本当に気持ちのいい constexpr
中3女子が狂える本当に気持ちのいい constexpr中3女子が狂える本当に気持ちのいい constexpr
中3女子が狂える本当に気持ちのいい constexpr
 
asm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web gamesasm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web games
 
Lisp Tutorial for Pythonista : Day 3
Lisp Tutorial for Pythonista : Day 3Lisp Tutorial for Pythonista : Day 3
Lisp Tutorial for Pythonista : Day 3
 
Vim scriptとJavaとHaskell
Vim scriptとJavaとHaskellVim scriptとJavaとHaskell
Vim scriptとJavaとHaskell
 
Ruby 3の型推論やってます
Ruby 3の型推論やってますRuby 3の型推論やってます
Ruby 3の型推論やってます
 
LastaFluteでKotlinをはじめよう
LastaFluteでKotlinをはじめようLastaFluteでKotlinをはじめよう
LastaFluteでKotlinをはじめよう
 
BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdf
 
BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdf
 
とあるFlashの自動生成
とあるFlashの自動生成とあるFlashの自動生成
とあるFlashの自動生成
 
Haskell Lecture 2
Haskell Lecture 2Haskell Lecture 2
Haskell Lecture 2
 
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
思ったほど怖くない! Haskell on JVM 超入門 #jjug_ccc #ccc_l8
 
20141128 iOSチーム勉強会 My Sweet Swift
20141128 iOSチーム勉強会 My Sweet Swift20141128 iOSチーム勉強会 My Sweet Swift
20141128 iOSチーム勉強会 My Sweet Swift
 

Recently uploaded

UPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdfUPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdffurutsuka
 
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Yuma Ohgami
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムsugiuralab
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略Ryo Sasaki
 
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxIoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxAtomu Hidaka
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Danieldanielhu54
 
PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000Shota Ito
 

Recently uploaded (7)

UPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdfUPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdf
 
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システム
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
 
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxIoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Daniel
 
PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000
 

How wonderful to be (statically) typed 〜型が付くってスバラシイ〜

  • 1. How wonderful to be (statically) typed ∼(静的に)型がつくってスバラシイ∼ 石井 大海
  • 2. 自己紹介 • 石井 大海 (id:mr_konn / @mr_konn) • 早稲田大学数学科三年 • 集合論や論理学、圏論に興味 • 2010 Summer Intern から PFI でバイト中 • Haskell Lover • Haskell でウェブ開発などしている
  • 3. 本日のお題:型 • 型がつくと何が嬉しいのか? • 型・・・むずかしそう • ムツカシイ理論ではなく応用例の紹介 • Haskell の布教ではない • 静的型付けの布教です。
  • 4. Table of Contents • 型とは何か?──型付け、型推論、型安全 • wonderful な型たち──型の表現力と応用 • いいとこ取り多相──型クラス • 型レベル函数:型族──キャスト、Map共通化など • そっちは残像だ──幽霊型はタグ • 洒落た多相の使い方──多相型でリーク防止 • Haskell、昇進す。──Data Kinds • その型、強力につき──依存型と証明
  • 5. Table of Contents • 型とは何か?──型付け、型推論、型安全 • wonderful な型たち──型の表現力と応用 • いいとこ取り多相──型クラス • 型レベル函数:型族──キャスト、Map共通化など • そっちは残像だ──幽霊型はタグ • 洒落た多相の使い方──多相型でリーク防止 • Haskell、昇進す。──Data Kinds • その型、強力につき──依存型と証明
  • 8. 型とは何か? • つまり? • 値の種類を区別するタグのようなもの • 世の言語は大きく「型付き言語」と「型無 し言語」に大別出来る • 型付き・・・C, Ruby, Haskell, LISP, Smalltalk... • 型無し・・・Brainf*ck, Lazy-K, ...
  • 9. 型なし……? • 実用的なプログラミング言語は全部型がついてる気が する。 • Tcl :すべては文字列。でも実際には型別の内部表現 を持っている(らしい)。 • そもそもの untyped・・・Untyped Lambda Calculus • 型あり言語の分類 • 動的型付け・・・LISP, Ruby, Smalltalk, JavaScript... • 静的型付け・・・Java, C, Haskell, OCaml, ...
  • 11. 動的と静的の違い • 動的型付け • 型検査は実行時に行われる • (compile-time) untyped と云える? • 以後「型なし」は「動的型付け」の alias とする • インタプリタ言語はこれが多い • 静的型付け • 型検査はコンパイル時に行われる • 型が合わないものは実行する前に弾かれる
  • 12. 型検査 • 演算の値の型が合っているか検査 • 合っていなかったら? • 言語によって弾いたり、キャストした りする。 → 型安全性
  • 13. 型安全性? • ナイーヴな定義:「型検査を通ったものが変な挙 動をしない」 • ちょっと厳密な定義 • Preservation: 型が評価の順番に依らない • Progress: 型が付いたら「刺さらない」 • 「刺さらない」ってなんや(意味論による)
  • 14. 型安全性と言語 • Haskell……型安全と云ってよい • 黒魔術を使わなければ型安全 • 停止性を込めると型安全じゃない • f x = f (f x) みたいなコードも型は付くが停止し ない • C……型安全じゃない! • cast や printf(“%s”, 12); などあぶない
  • 15. 型推論 • 函数の型を自動的に推論してくれる機能 • 型推論なし・・・C, Java, ... • 型推論あり・・・Haskell, Scala, OCaml, ... • 健全性とか完全性とか色々概念があるらしいです がぶっちゃけよくわからない • 色んな強さの型推論がある、と云うことで。 • コンパイラが付けられない部分は手で注釈
  • 16. ここからは • 静的型付け、型推論あり言語の布教 • かつある程度の型安全性を持つ言語 • Preserve は当然仮定 • 停止しないくらいは許す • SEGV ったりしない、程度。
  • 17. その前に……なぜ型? • 型はドキュメント • 型を見れば(ある程度)挙動がわかる • 勿論 Int → Int とか見せられてもわか らない ^^;(でも無いよりマシ) • 型検査通ればある程度正しく動く • どの程度?→型の表現力による!
  • 18. 型はドキュメント • SMTP 通信用の型 • 複数値を取るリスト型や、値を取らないかも しれない Maybe 型などが雄弁に語る data SMTPCommand = HELO ByteString | EHLO ByteString | MAIL Path [(ByteString, ByteString)] | RCPT Path [(ByteString, ByteString)] | DATA ByteString | RSET | VRFY ByteString | EXPN ByteString | HELP (Maybe ByteString) | NOOP (Maybe ByteString) | QUIT data Path = Path [ByteString] Mailbox | Empty
  • 19. 型はドキュメント • 各 ByteString が何を指すのかわからない…… • 型に別名を付けるとわかりやすい! • 中身としては同じ。見通しはよくなる type Domain = ByteString type Param = (ByteString, ByteString) data SMTPCommand = HELO Domain | EHLO Domain | MAIL Path [Param] | RCPT Path [Param] | DATA ByteString | RSET | VRFY ByteString | EXPN ByteString | HELP (Maybe ByteString) | NOOP (Maybe ByteString) | QUIT data Path = Path [Domain] Mailbox | Empty
  • 20. wonderful な型たち ──型の表現力と応用──
  • 21. 型クラス • Ad-hoc 多相を実現する機構 • 複数の型に共通な演算をオーバーロード • cf. Parametric 多相:共通の「実装」を共有する • 代替手法 • 強力なモジュールシステム(like Alloy, Agda, OCaml, ...) • プリプロセッサ(camlp4?)
  • 22. 数値型クラス class (Eq a, Show a) => Num a where (+), (-), (*) :: a -> a -> a negate :: a -> a abs :: a -> a signum :: a -> a fromInteger :: Integer -> a x - y = x + negate y negate x = 0 - x • 数値としての特徴を持つ型のクラス • 加減乗除、反転、絶対値、数字からの変換など • Num である為には Eq, Show でもある必要がある • 型クラスは、型への「制約」「述語」として考えられる
  • 23. ファンクタ型クラス class Functor f where fmap :: (a -> b) -> f a -> f b • 普通の函数を「持ち上げ」られるコンテナのよう なもの • []、Maybe、IO などなど • Maybe a は値を持つが、 Maybe は値を持たない • Maybe :: * → * :型を受けとって型を返す「函 数」みたいなもの
  • 24. 多引数型クラスの例 class Monad m => MonadState s m | m -> s where get :: m s get = state (s -> (s, s)) put :: s -> m () put s = state (_ -> ((), s)) state :: (s -> (a, s)) -> m a state f = do s <- get let ~(a, s) = f s put s return a • 「m は内部状態 s を持つモナド」 • (モナド=すごいコンテナ) • m を決めると s が決まる:「m → s」関数従属性
  • 25. 型クラス:まとめ • 型の述語のようなもの • Ad-hoc 多相を綺麗に実現する • 函数従属性で依存関係を記述出来る
  • 27. 例1: MonadStateの書き換え class Monad m => MonadState m where type State m :: * get :: m (State m) get = state (s -> (s, s)) put :: State m -> m () put s = state (_ -> ((), s)) state :: (State m -> (a, State m)) -> m a state f = do s <- get let ~(a, s) = f s put s return a • State m が今までの s • 型名がドキュメントの役割を果している • 複雑なFunDepsを無くし、かつ一引数クラスで書ける
  • 28. 例2:演算キャスト class Add a b where type SumType a b add :: a -> b -> SumType a b instance Add Int Int where type SumType Int Int = Int add = (+) instance Add Int Double where type SumType Int Double = Double a `add` b = fromIntegral a + b • 二つの型の足し算を定義 • SumType はキャストされた結果の型
  • 29. 例3:マップの一般化 lass Key k where data Map k :: * -> * empty :: Map k v lookup :: k -> Map k v -> Maybe v insert :: k -> v -> Map k v -> Map k v instance Key Int where newtype Map Int a = IMap (IM.IntMap a) empty = IMap IM.empty lookup k (IMap d) = IM.lookup k d insert k v (IMap d) = IMap $ IM.insert k v d instance Key ByteString where newtype Map ByteString a = BSMap (Trie a) instance (Key a, Key b) => Key (a, b) where newtype Map (a, b) v = TMap (Map a (Map b v)) • 辞書構造をキーの型によって使いわけ
  • 30. 洒落た多相の使い方 • いままでの多相型の使い方 • ad-hoc • 複数の型に共通な操作を抽象化。 • Num, Functor, Monad,... • parametric • 中身を抽象化したコンテナなど • リスト, Map, a → a, ...
  • 31. 残像だ──幽霊型 • 幽霊型(phantom types) • 実際のデータ定義に出て来ない型引数 を取る型 • データにタグを付けることが出来る • GADTs と云う機構を使って制御出来る
  • 32. 例:構文木 • 型付き言語の構文木を書きたい data Expr = Zero | Succ Expr | Plus Expr Expr | Yes | No | IsZero | Apply Expr Expr eval :: Expr -> Expr eval Zero = Zero eval (Succ a) = Succ $ eval a eval (Plus a (eval -> Zero)) = eval a eval (Plus a (eval -> Succ b)) = Succ $ eval $ Plus a b eval Yes = Yes eval No = No eval (Apply IsZero (eval -> Zero)) = Yes eval (Apply IsZero _) = No eval IsZero = IsZero eval _ = error "type error"
  • 33. 実行例 ghci> eval (Plus Zero (Succ (Succ Zero))) Succ (Succ Zero) ghci> eval (Plus (Succ Zero) (Succ (Succ Zero))) Succ (Succ (Succ Zero)) ghci> eval (Apply IsZero (Succ Zero)) No ghci> eval (Apply IsZero (Plus Zero Zero)) Yes ghci> eval (Plus Yes Zero) Yes ghci> eval (Apply IsZero (Succ Yes)) No ghci> eval (Plus Zero Yes) *** Exception: type error • 型があわないのが実行時エラーになる • 素朴にやるとエラーが……。一々チェック?
  • 36. 例:型付き構文木 data Expr a where Zero :: Expr Int Succ :: Expr Int -> Expr Int Plus :: Expr Int -> Expr Int -> Expr Int Yes :: Expr Bool No :: Expr Bool IsZero :: Expr (Int -> Bool) Apply :: Expr (a -> b) -> Expr a -> Expr b eval :: Expr a -> Expr a eval (Succ a) = Succ (eval a) eval (Plus a b) = eval a eval (Plus a (eval -> Succ b)) = Succ (eval $ Plus a b) eval (Apply IsZero (eval -> Zero)) = Yes eval (Apply IsZero (eval -> Succ _)) = No eval a = a • 各コンストラクタに型が付加されている • 変な構文木を弾いてくれる!
  • 38. 型引数の威力 • 型引数は「階層の区別」に使える • タグとしての型引数 • 「ランク2多相」と組み合わせると、安 全なメモリアクセスやリソース管理に 使える
  • 39. Rank 2 多相? • 多相函数を引数に取れる型拡張 • Haskell の総称プログラミングライブ ラリSYBなどにも使われる • ここではちょっと違った例を見ます。
  • 40. ST Monad • State thread: メモリを用いた高速な状態 更新をするための機構 • Haskell は pure なので外に inpure な操作 が漏れないようにしたい
  • 41. ST Monad data ST s a -- 内部状態 s を持ち、a の値を返す演算。 data STRef s a -- 内部状態 s を持ち、a の値を保持する可変値。 -- これも s を漏らしてはいけない。 newSTRef :: a -> ST s (STRef s a) -- 新しい STRef を作る。その際 ST と STRef の内部状態は統一する。 readSTRef :: STRef s a -> ST s a writeSTRef :: STRef s a -> a -> ST s () modifySTRef :: STRef s a -> (a -> a) -> ST s () -- STRef を読み書きするための函数。ST内部でしか使えない。 runST :: (forall s. ST s a) -> a -- ST 演算を実行して、結果を返す函数。 -- 内部状態は捨てられるので純粋性は保たれる。
  • 42. 利用例 f str = do ref <- newSTRef str modifySTRef ref (++ ", that is the value") readSTRef ref main :: IO () main = do print $ runST $ f "hoge" • 簡単な例 • 破壊的代入を行えるので、STArray など 高速な配列演算を行うための型もある • Bloom Filter の実装などにも使われる
  • 43. 外部に漏れない? leaker str = do ref <- newSTRef str modifySTRef ref (++ ", that is the value") return ref main :: IO () main = do let ref = runST $ leaker "hoge" print $ runST $ anotherEvilSToperation ref • STRef を外に返すような函数を書けば漏 れるんじゃないの?
  • 44. コンパイルしてみる /Users/hiromi/pfi/seminar-20120411/test01.lhs:121:11: Couldn't match type `a0' with `STRef s [Char]' because type variable `s' would escape its scope This (rigid, skolem) type variable is bound by a type expected by the context: ST s a0 In the second argument of `($)', namely `leaker "hoge"' In the second argument of `($)', namely `runST $ leaker "hoge"' In the expression: print $ runST $ leaker "hoge" Failed, modules loaded: none. • STRef s [Char] の s は ST の内部状態と同じ • s は runST :: (forall s. ST s a) → a の引数内側で束縛 • 何でもいい、だからこそ何だかわからない!
  • 45. ちょっと理由説明 • runST :: (forall s. ST s (STRef s a)) → forall s. STRef s a • と云う型じゃだめなの? • 束縛変数の記号を変えてもいいので…… • (forall s’. ST s’ (STRef s’ a)) → forall s. STRef s a • と書き換えることも出来て、型があわない
  • 46. さらに応用:リソース管理 • 問題:Handle など scarce なリソースはすぐに解放した い • リソース取得と解放とが同順とは限らない • 解放したリソースを外でアクセス出来ないようにし たい • 「リージョン」を使う! • 同一リージョン中は割り当てたリソースが使用可 能、抜けると解放しアクセス不可能に
  • 47. 実装方針 • ST を真似て Rank 2 多相で leak を防ぐ • 内部状態ではなくただのタグ、幽霊型 • 同順じゃなく解放するには? • リージョンをネスト • 型クラス+モナド変換子で親リージョ ンのリソースを割り当てられるように
  • 48. 実装 newtype RIO s a = RIO (ReaderT (IORef [Handle]) IO a) deriving (Functor, Monad, MonadReader (IORef [Handle])) newtype RHandle s = RHandle Handle runRIO :: (forall s. RIO s a) -> IO a runRIO (RIO act) = bracket (newIORef []) (readIORef >=> mapM_ hClose) $ runReaderT act openFileR :: FilePath -> IOMode -> RIO s (RHandle s) openFileR fp mode = do h <- RIO $ liftIO $ openFile fp mode RIO $ ReaderT $ ref -> liftIO $ modifyIORef ref (h:) return (RHandle h) • 開いたハンドルへの参照を持っておく • 終了時に解放するようにする • ハンドルは全てRHandle の形で扱い、閉じれない
  • 49. 使ってみる test = do h <- openFileR "conf.txt" ReadMode str <- hGetLineR h putStrLnR str main = runRIO test • 型は省略しても推論してくれる(!!) • 上の実装だと一リージョンしか扱えな いが、型クラスによってネスト出来る
  • 50. やりたい例 RIO s IO RIO t (RIO s IO)
  • 51. やりたい例 1 ファイル1を開く h1 :: RHandle s RIO s IO RIO t (RIO s IO)
  • 52. やりたい例 1 ファイル1を開く h1 :: RHandle s RIO s IO RIO t (RIO s IO)
  • 53. やりたい例 1 ファイル1を開く h1 :: RHandle s RIO s IO RIO t (RIO s IO) h1 2 設定ファイルを開く を渡す
  • 54. やりたい例 1 ファイル1を開く h1 :: RHandle s RIO s IO RIO t (RIO s IO) h1 2 設定ファイルを開く h2, hc :: RHandle t を渡す 3 ファイル2の位置を読み、開く
  • 55. やりたい例 1 ファイル1を開く h1 :: RHandle s RIO s IO RIO t (RIO s IO) h1 2 設定ファイルを開く h2, hc :: RHandle t を渡す 3 ファイル2の位置を読み、開く 4 ファイル3を(親リージョンで)開く h3 :: RHandle s
  • 56. やりたい例 1 ファイル1を開く h1 :: RHandle s RIO s IO RIO t (RIO s IO) h1 2 設定ファイルを開く h2, hc :: RHandle t を渡す 3 ファイル2の位置を読み、開く 4 ファイル3を(親リージョンで)開く h3 :: RHandle s 5 1, 2の内容を交互に3へ書き込む
  • 57. やりたい例 1 ファイル1を開く h1 :: RHandle s RIO s IO RIO t (RIO s IO) h1 2 設定ファイルを開く h2, hc :: RHandle t を渡す 3 ファイル2の位置を読み、開く 4 ファイル3を(親リージョンで)開く h3 :: RHandle s 5 1, 2の内容を交互に3へ書き込む h2, hc を解放 h3 を返す; h3は型があうので返せる
  • 58. やりたい例 1 ファイル1を開く h1 :: RHandle s RIO s IO RIO t (RIO s IO) h1 2 設定ファイルを開く h2, hc :: RHandle t を渡す 3 ファイル2の位置を読み、開く 4 ファイル3を(親リージョンで)開く h3 :: RHandle s 5 1, 2の内容を交互に3へ書き込む h2, hc を解放 h3 を返す; h3は型があうので返せる 6 1 に残りがあれば それを 3へ書き込む
  • 59. やりたい例 1 ファイル1を開く h1 :: RHandle s RIO s IO RIO t (RIO s IO) h1 2 設定ファイルを開く h2, hc :: RHandle t を渡す 3 ファイル2の位置を読み、開く 4 ファイル3を(親リージョンで)開く h3 :: RHandle s 5 1, 2の内容を交互に3へ書き込む h2, hc を解放 h3 を返す; h3は型があうので返せる 6 1 に残りがあれば それを 3へ書き込む h3, h1 を解放
  • 60. そのまま書ける test3 = runSIO $ do h1 <- newSHandle "/tmp/SafeHandles.hs" ReadMode h3 <- newRgn (test3_internal h1) till (shIsEOF h1) (shGetLine h1 >>= shPutStrLn h3) shReport "test3 done" test3_internal h1 = do h2 <- newSHandle "/tmp/ex-file.conf" ReadMode fname <- shGetLine h2 h3 <- liftSIO (newSHandle fname WriteMode) shPutStrLn h3 fname till (liftM2 (||) (shIsEOF h2) (shIsEOF h1)) (shGetLine h2 >>= shPutStrLn h3 >> shGetLine h1 >>= shPutStrLn h3) shReport "Finished zipping h1 and h2" return h3 • ネストしても推論してくれる! • 勝手にタグがつく! • リソースの受け渡しも型が監視してくれる!
  • 61. 幽霊型・Rank 2多相 他の応用例 • セッション型 • ネットワーク/スレッド通信のチャネ ルの「使われ方」の不整合を型が検 出してくれる
  • 62. Session 型の例 typecheck1 $ c -> send c "abc" :: (Length ss l) => Session t (ss :> Send [Char] a) (ss :> a) () example from [10] • 操作が 型レベルリストで並んでいる • Session t (事前条件) (事後条件) 結果 • 上の例は「一度だけ、一つだけチャネ ルを使って文字列をを送る」と読む • t は Rank 2 多相によるリーク防止
  • 63. 昇進──Data Kinds • Data Kinds? • データ型を型レベルへ「持ち上げ」 • GADTs や Type Family などと組み合わ せて強力な威力を発揮する
  • 64. 例:長さ付きリスト • 幽霊型として、長さをパラメタ化 • 空リストへの先頭要素、tail アクセスを 防止 • 連結の際は型レベル足し算がいる • type family で足せばいい!
  • 65.
  • 66. 実装例 data Nat = Z | S Nat data Vector :: Nat -> * -> * where Nil :: Vector Z a Cons :: a -> Vector n a -> Vector (S n) a vhead :: Vector (S n) a -> a vhead (Cons a _) = a vtail :: Vector (S n) a -> Vector n a vtail (Cons _ as) = as vnull :: Vector n a -> Bool vnull Nil = True vnull _ = False type family (a :: Nat) :+: (b :: Nat) :: Nat type instance Z :+: a = a type instance S n :+: a = S (n :+: a) vappend :: Vector n a -> Vector m a -> Vector (n :+: m) a vappend Nil v = v vappend (Cons a as) v = Cons a (as `vappend` v)
  • 67. 以前は…。 • Nat を型に持ち上げられなかったので 無意味な足し算が定義出来る可能性が あった • 同様に長さ以外のインデックスが付く 可能性があった • 持ち上げる事で範囲を制限!
  • 68. 補足 • Data Kinds が強力になり、型が引数として任 意の値を取れるようになる(!!) • 依存型と云う • Coq, Agda など • Curry-Howard 対応 • 型と論理式の対応→定理証明
  • 70. References 1. “Fun with type functions”, Oleg Kiselyov, Simon Peyton Jones and Chung-chieh Shan, 2010 2. “Giving Haskell a Promotion”,B. A.Yorgey, S. Weirich, J. Cretin, Simon Peyton Jones and D.Vytiniotis, 2011 3. “Lightweight Monadic Regions”, Oleg Kiselyov, Chung-chieh Shan, 2008 4. “Algebra of Programming in Agda”, Shin-Cheng Mu, Hsiang-Shang Ko, Patrik Jansson, 2009 5. “Yesod Web Framework for Haskell” 6. “データ型 - Wikipedia”, Wikipedia 7. “Type safety - Wikipedia”, Wikipedia 8. “Phantom type - HaskellWiki”, HaskellWiki 9. “Region-based resource management”, Oleg Kiselyov, 2011 10. “full-sessions-0.6.1”, id:keigoi 11. “プログラミングCoq”, 池渕未来

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. &amp;#x6700;&amp;#x65B0;&amp;#x7248; GHC &amp;#x304B;&amp;#x3089; Num &amp;#x306F; Eq &amp;#x3082; Show &amp;#x3082;&amp;#x8981;&amp;#x6C42;&amp;#x3057;&amp;#x306A;&amp;#x304F;&amp;#x306A;&amp;#x308A;&amp;#x307E;&amp;#x3057;&amp;#x305F;&amp;#x3002;\n
  23. &amp;#x6700;&amp;#x65B0;&amp;#x7248; GHC &amp;#x304B;&amp;#x3089; Num &amp;#x306F; Eq &amp;#x3082; Show &amp;#x3082;&amp;#x8981;&amp;#x6C42;&amp;#x3057;&amp;#x306A;&amp;#x304F;&amp;#x306A;&amp;#x308A;&amp;#x307E;&amp;#x3057;&amp;#x305F;&amp;#x3002;\n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. Hoare &amp;#x7BC0;&amp;#x307F;&amp;#x305F;&amp;#x3044;&amp;#x306A;&amp;#x3082;&amp;#x306E;&amp;#xFF1F;\n
  68. \n
  69. \n
  70. \n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n