次の型指定されていないコードを型付きのラケットに変換したいとします。これらの関数は、SICPに触発され、純粋に関数からデータ構造を構築する方法を示しています。多型ユニオン型の出現型
(define (make-pair x y)
(lambda (c)
(cond
((= c 1) x)
((= c 2) y)
(error "error in input, should be 1 or 2"))))
(define (first p) (p 1))
(define (second p) (p 2))
ラケットを入力するためにまっすぐにそれを変換するには、make-pair
関数の戻り値は(: make-pair (All (A B) (-> A B (-> Number (U A B)))))
のようです。これに続いて、first
のタイプは(: first (All (A B) (-> (-> Number (U A B)) A)))
でなければなりません。しかし、関数を実装しているときには、が型A
のみを返すことを確認するために何らかの種類の型を入力する必要があるため、(p 1)
を直接呼び出すことはできません。 first
から(U A B)
の戻り値の型を変更すると、オカレンス型の負担はユーザー側で、API側では発生しません。したがって、このシナリオでは、first
内にオカレンス型を使用する方法(つまり、型変数A
の述部をどのように使用するか)を使用して、ペアの最初のコンポーネントのみを安全に返すことができますか?
UPDATE
Iは、上から少し異なり、make-pair
関数の引数として供給されるA
とB
ための述語が必要なアプローチを試みました。以下のコードです:
#lang typed/racket
(define-type FuncPair (All (A B) (List (-> Number (U A B)) (-> A Boolean) (-> B Boolean))))
(: make-pair (All (A B) (-> A B (-> A Boolean) (-> B Boolean) (FuncPair A B))))
(define (make-pair x y x-pred y-pred)
(list
(lambda ([c : Number])
(cond
((= c 1) x)
((= c 2) y)
(else (error "Wrong input!"))))
x-pred
y-pred))
(: first (All (A B) (-> (FuncPair A B) Any)))
(define (first p)
(let ([pair-fn (car p)]
[fn-pred (cadr p)])
(let ([f-value (pair-fn 1)])
(if (fn-pred f-value)
f-value
(error "Cannot get first value in pair")))))
しかし、これはあなたの質問の開始時に型指定されていないコードからエラーexpected: A given: (U A B) in: f-value