2017-05-10 8 views
0

になることを「約束」へ:どのように入力された/ラケットでこの機能を持っている場合は値が特定のタイプ

(: random-if-empty (-> (U Image-Color "empty") Image-Color)) 
(define (random-if-empty s) 
    (cond 
    [(equal? s "empty") (random-color)] 
    [else s])) 

それの入力が"empty"の場合はランダムな色を返し、そうでなければ、それは入力です返し、どのようにして([else s])が、Image-Colorの代わりにImage-Colorまたは"empty"であるとタイプチェッカーが言わなくなるのですか?それとも全体的にこれを行うための良い方法がありますか?私はtyped/2htdp/imageライブラリを使用しています。ここにはImage-Colorがあります。

答えて

0

equal?述部は、変数が特定の値であるかどうかを型システムに通知できますが、これは特定の型の特定の値に対してのみ機能します。単純な型(ブール値、シンボル、空リスト、void、0、、)で動作しますが、文字列を含む他のほとんどのデータ型では機能しません。

(これは、文字列は変更可能であることとは何かを持っているかもしれませんが、私はよく分からない。)

これを解決する方法が"empty"文字列別の方法について、独自の述語を作ることです。型付きラケットは、フォーム「make-predicate」を提供し、いくつかの単純な「フラット」型を述語に変換できます。

(define my-empty-pred? (make-predicate "empty")) 

この新しい述語が(my-empty-pred? x) trueを返した場合、その後、xはタイプ"empty"を持っていることを型システムを伝えるために、より直接的にoccurrence typingを使用することができます、そしてそれは、その後x falseを返す場合:あなたはこのようにそれを使用することができますタイプに"empty"を含めることはできません。だからあなたのようなあなたの例でそれを使用することができます:

(: random-if-empty (-> (U Image-Color "empty") Image-Color)) 
(define (random-if-empty s) 
    (cond 
    [(my-empty-pred? s) (random-color)] 
    [else s])) 
0

occurrence typingを利用して、タイプチェッカーに、後者の場合のsが文字列でないことを伝えることができます。

#lang typed/racket 

(require typed/2htdp/image) 

(define (random-color) : Image-Color 
    (color 0 0 0)) ;; dummy 

(: random-if-empty (-> (U Image-Color "empty") Image-Color)) 
(define (random-if-empty s) 
    (cond 
    [(string? s) (random-color)] 
    [else s])) 

なぜstring?仕事ではなく(equal? s "empty)"?私は知らないが、Typed Racketはそれほどスマートではないと思う。あなたのタイプは本当にあなたがちょうど主張するように書かれている、castingに頼る必要がある場合があります複雑されている場合は

またassertions

(: random-if-empty (-> (U Image-Color "empty") Image-Color)) 
(define (random-if-empty s) 
    (cond 
    [(equal? s "empty") (random-color)] 
    [else (assert s string?)])) 

を使用することができます。しかし、私はこれらの解決策を優先順に挙げました。鋳造は最後の手段でなければなりません。

+0

私はそれが等しいとは思わない?それは述語ではないからです。 – Vityou

+0

'文字列? 'に変更すると、' Image-Color'が文字列の場合、プログラムの動作が変わります。 'typeed/2htdp/image'で可能なので、Gibstickの最初の解決策は間違っています。 –

関連する問題