2017-06-13 17 views
0

型付きラケットのRecタイプは、再帰的な型を作るための簡単な方法です:再帰的な契約は

#lang typed/racket/base 

(define (deep (n : Integer)) : (Rec T (U Integer (List T))) 
    (if (zero? n) 
    n 
    (list (deep (- n 1))))) 

は、再帰的な契約をする同様の方法はありますか? ラケットのrecursive-contractは同じではありません。

+0

Slack on Original Q/A:https://racket.slack.com/archives/C06V96CKX/p1496706050248551 –

答えて

0

契約表現は単なる式です!型付きラケットのRecのような入力を受け取り、 "再帰的識別子"を自己参照で置き換えるマクロを書くことができます。

ここ(rec/c id ctc)(recursive-contract id)に置き換えidのすべての出現でctcに展開例rec/cコンビネータは、です。

#lang racket/base 
(require racket/contract (for-syntax racket/base syntax/parse)) 

(define-syntax-rule (rec/c t ctc) 
    (letrec ([rec-ctc 
      (let-syntax ([t (syntax-parser (_:id #'(recursive-contract rec-ctc)))]) 
       ctc)]) 
     rec-ctc)) 

(define/contract (deep n) 
    (-> integer? (rec/c t (or/c integer? (list/c t)))) 
    (if (zero? n) 
    n 
    (list (deep (- n 1))))) 

(deep 4) 

注:識別子としてtの任意の使用と一致_:idパターン。