kb84tkhrのブログ

何を書こうか考え中です あ、あと組織とは関係ないってやつです 個人的なやつ

Typed Racketのお勉強 (1)

Typed RacketはRacketに型を付けたものです

The Typed Racket Guideを見ながら勉強していきます
詳細はThe Typed Racket Reference

1 Quick Start

とりあえずこれをやれと

  • ソース先頭の#lang racket#lang typed/racketに変える
  • (require mod)(require typed/mod)に変える
  • Structureの定義およびトップレベルの定義を型で修飾する

#lang typed/racket

(struct pt ([x : Real] [y : Real]))

(: distance (-> pt pt Real))
(define (distance p1 p2)
  (sqrt (+ (sqr (- (pt-x p2) (pt-x p1)))
           (sqr (- (pt-y p2) (pt-y p1))))))

->が関数ってことですね
どことなくHaskellっぽい

どれどれ

> (distance (pt 0 0) (pt 3 4))
- : Real
5

REPLは値だけでなく型も表示してくれます
ちゃんと型チェックしてくれているか

> (distance 3 4)
Type Checker: type mismatch
  expected: pt
  given: Positive-Byte in: 3
Type Checker: type mismatch
  expected: pt
  given: Positive-Byte in: 4
Type Checker: Summary: 2 errors encountered in:
  3
  4

よしよし

2 Beginning Typed Racket

  • #lang typed/racketはTyped Racketを使うよという宣言
  • structには型修飾を付ける
  • (-> pt pt Real)は関数の型
    • ->が関数のしるし
    • 最後の型(Real)が戻り値の型

関数自身を評価すれば関数自身の型も表示できます

> distance
- : (-> pt pt Real)
#<procedure:distance>

:print-typeも使えます

> (:print-type distance)
(-> pt pt Real)

こっちの方が表示はすっきり

2.1 Datatypes and Unions

  • UはUnion型の定義
  • define-typeで型に名前をつける

こう

(define-type Tree (U leaf node))
(struct leaf ([val : Number]))
(struct node ([left : Tree] [right : Tree]))

参照はこんな感じ
structで定義したときにleft-valnode-leftも勝手に定義されています

(define t1 (node (leaf 1) (leaf 2)))
(leaf-val (node-left t1)) 

関数定義
組み込み型でも自分で定義した型でも書き方は同じ

(: tree-height (-> Tree Integer))
(define (tree-height t)
  (cond ((leaf? t) 1)
        (else (max (+ (tree-height (node-left t)) 1)
                   (+ (tree-height (node-right t)) 1)))))

(leaf? t)tleaf型かどうかを判定しています
これも勝手に定義されます