2009-08-04 8 views
12

Je discutais avec Sadek Drobi sur twitter quand on m'a dit que F # ne semblait pas supporter Infinite Types. Il se trouve que dans C#, vous pouvez faire quelque chose le long de ces lignes:Les types infinis (types récursifs) ne sont-ils pas possibles en F #?

delegate RecDelegate<T> RecDelegate<T>(T x); 

Cependant, après quelques essais sur nos deux parties, nous avons déterminé que la même chose dans F # semble impossible à la fois implicite et explicite.

explicite:

type 'a specialF = 'a->specialF<'a> 

erreur FS0191: Cette définition de type implique une référence cyclique immédiate par une abréviation, champ struct ou relation d'héritage.

Implicite:

let rec specialF (x: 'a) = specialF 

Type mismatch. Attend un 'b mais étant donné un' a -> 'b. Le type résultant serait infini en unifiant '' b '' et '' a -> 'b'.

Bien sûr, ce sont des échantillons intentionnellement simples. Je me demandais si je me trompais d'une façon ou d'une autre. Peut-être ai-je manqué un type d'annotation nécessaire?

+0

Y a-t-il une application pratique ici, ou la question était-elle juste le résultat d'une recherche pour le plaisir? – Brian

+1

Pour autant que je sache, il n'y a pas d'applications pratiques, référentielles et transparentes. Cependant, un exemple serait qu'avec un certain type d'état fermé mutable, cela peut être utile pour des applications répétées. ex: add (1) (2) (3) (4) - où n'importe quel nombre d'applications peut être fait. –

+0

Voici un programme OCaml que j'ai écrit qui utilise cette fonctionnalité pour éviter un niveau d'indirection utilisant des rectangles. http://www.ffconsultancy.com/languages/ray_tracer/code/1/ray.ml –

Répondre

7

Vous pouvez aussi faire quelque chose comme

type 'a RecType = RecType of ('a -> 'a RecType) 

pour créer un type nommé par lequel effectuer la récursion. Maintenant cela fonctionne:

let rec specialF = RecType (fun _ -> specialF) 
+0

Je serais également intéressé si la version plus générale fonctionne: http://stackoverflow.com/questions/1253374/explicit-type -recursion-en-f –

6
type d<'T> = delegate of 'T -> d<'T> //' 
let del : d<int> = null 
let anotherDel = del.Invoke(1).Invoke(2).Invoke(3) 

Je pense que vous avez besoin d'un type nommé qui est représentable directement dans CLI pour briser la récursion, donc en F # cela signifie que vous avez besoin d'un délégué de type réel ainsi.

3

Les types d'enregistrements récursifs devraient également fonctionner.

type A = { A : A } 
let rec a : A = { A = a } 

Je serais intéressé par une application pratique. Ou même un peu pratique :)

Questions connexes