2017-05-10 1 views
0

Si j'ai cette fonction dans tapée/raquette:Comment la « promesse » qu'une valeur sera un certain type

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

qui retourne une couleur au hasard si elle est entrée est "empty", sinon il renvoie son entrée, comment puis-je arrêter le vérificateur de type de dire que s (en [else s]) peut être un Image-Colorou"empty" au lieu du Image-Color attendu? Ou y a-t-il un meilleur moyen de le faire? J'utilise la bibliothèque typed/2htdp/image, d'où provient Image-Color.

Répondre

0

Le prédicat equal? peut informer le système de type qu'une variable est ou n'est pas une certaine valeur, cependant, cela ne fonctionne que pour certaines valeurs de certains types. Cela fonctionne pour certains types simples (booléens, symboles, listes vides, void et 0 et 1), mais cela ne fonctionne pas pour la plupart des autres types de données, y compris les chaînes.

(Cela pourrait avoir quelque chose à voir avec les chaînes étant mutable, je ne suis pas sûr.)

La façon de résoudre ce problème est de faire votre propre prédicat pour la chaîne "empty" une manière différente. La raquette dactylographiée fournit le formulaire make-predicate qui peut transformer certains types "plats" simples en prédicats. Vous pouvez l'utiliser comme ceci:

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

Ce nouveau prédicat sera en mesure d'utiliser occurrence typing plus directement pour indiquer au système de type que si (my-empty-pred? x) renvoie true, alors x a le type "empty", et si elle retourne false alors x Le type ne doit pas contenir "empty". Donc, vous pouvez l'utiliser dans votre exemple comme:

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

Vous pouvez tirer parti de occurrence typing pour indiquer au vérificateur de type que votre s dans le deuxième cas ne peut pas être une chaîne.

#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])) 

Pourquoi est-ce string? travail et non (equal? s "empty)"? Je ne sais pas, mais je suppose que Typed Racket n'est pas si intelligent.

Vous pouvez également utiliser 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?)])) 

Si vos types vous sont vraiment compliqué peut avoir recours à casting, qui sont écrites comme affirme. Mais j'ai donné ces solutions dans l'ordre de préférence. Le casting devrait être un dernier recours.

+0

Je suppose que cela ne fonctionne pas à égalité? parce que ce n'est pas un prédicat. – Vityou

+0

Le changer en 'string?' Change le comportement du programme si un 'Image-Color' peut être une chaîne. Puisque dans 'typed/2htdp/image' il peut le faire, la première solution de Gibstick est fausse. –