2010-08-27 3 views
7

Les programmeurs Ocaml peuvent utiliser des 'types fantômes' pour imposer certaines contraintes à l'aide du système de types. Un bel exemple peut être trouvé au http://ocaml.janestreet.com/?q=node/11.Implémentation des types fantômes dans F #

La syntaxe type readonly ne fonctionne pas en F #. Il pourrait être remplacé par un pseudo-type fantôme défini comme type readonly = ReadOnlyDummyValue afin de mettre en œuvre les astuces dans le billet de blog mentionné ci-dessus.

Existe-t-il un meilleur moyen de définir les types fantômes en F #?

+4

avez-vous lu http://blog.matthewdoig.com/?p=134 et http://blog.matthewdoig.com/?p=138? –

+0

Merci pour les liens. J'ai raté ceux-là. –

+1

Le blog de matthewdoig est mort, mais les articles sont sur archive.org: http://web.archive.org/web/20100615031828/http://blog.matthewdoig.com/?p=134 http: //web.archive .org/web/20100615031841/http: //blog.matthewdoig.com/? p = 138 –

Répondre

14

Je pense que le type de définition utilisant simplement type somename ne fonctionnera pas dans F #. Le compilateur F # doit générer un certain type .NET à partir de la déclaration et la spécification F # ne définit pas explicitement ce qui devrait arriver pour les types fantômes.

Vous pouvez créer un type concret (par exemple avec type somename = ReadOnlyDummyValue) dans le fichier d'implémentation (.fs) et masquer les composants internes du type en ajoutant simplement type somename au fichier d'interface (.fsi). De cette façon, vous obtenez assez proche d'un type fantôme - l'utilisateur en dehors du fichier ne verra pas les internes du type.

Une autre alternative intéressante serait d'utiliser des interfaces. Cela me semble logique, car l'interface vide est probablement le type le plus simple que vous pouvez déclarer (et n'introduit pas d'identifiants factices). Interface vide ressemble à ceci:

type CanRead = interface end 
type CanWrote = interface end 

La chose intéressante, dans ce cas, est que vous pouvez également créer des interfaces héritées:

type CanReadWrite = 
    inherit CanRead 
    inherit CanWrite 

Ensuite, vous pouvez écrire une fonction qui peut prendre des valeurs de type Ref<CanRead, int> mais également des valeurs de type Ref<CanReadWrite, int> (parce que ces valeurs prennent également en charge la lecture):

let foo (arg:Ref<#CanRead, int>) = // ...  

Cela semble être quelque chose qui pourrait être u serein. Je serais en fait très intéressé si cela peut aussi être fait dans OCaml (parce qu'il repose sur le support F # pour les interfaces et l'héritage).

+0

La suggestion d'utiliser des interfaces est géniale. Merci! –

+0

@Tomas: Cela peut aussi être fait dans OCaml, bien sûr. –

+0

@Jon: Je m'attendais à ça. Je ne savais pas comment et ne pouvais pas trouver une bonne source d'information. Avez-vous un lien vers un exemple (de préférence librement disponible ;-))? –

Questions connexes