2009-08-04 22 views
12

Estaba chateando con Sadek Drobi en twitter cuando me enteré de que F # no parecía ser compatible con Infinite Types. Resulta que en C# que puede hacer algo en este sentido:¿No son posibles los tipos infinitos (también conocidos como tipos recursivos) en F #?

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

Sin embargo, después de algunos experimentos por ambas partes, se determinó que la misma en Fa # parece imposible tanto implícita y explícita.

explícito:

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

FS0191 error: Esta definición de tipo implica una referencia cíclica inmediata a través de una abreviatura, campo struct o relación de herencia.

implícita:

let rec specialF (x: 'a) = specialF 

de coincidencia de tipos. Esperando un 'b pero dado un' a -> 'b. El tipo resultante sería infinito al unificar '' b ' y' 'a ->' b '.

Por supuesto, estas son muestras intencionalmente simples.

Me preguntaba si de alguna manera estoy equivocado. Tal vez me perdí algún tipo de anotación necesaria?

+0

¿Hay alguna aplicación práctica aquí, o fue la pregunta solo el resultado de investigar por diversión? – Brian

+1

Por lo que yo entiendo, no hay aplicaciones prácticas referencialmente transparentes. Sin embargo, un ejemplo sería que con algún tipo de estado mudable cerrado esto puede ser útil para aplicaciones repetidas. ex: add (1) (2) (3) (4) - donde se puede hacer cualquier cantidad de aplicaciones. –

+0

Aquí hay un programa OCaml que escribí que usa esta característica para evitar un nivel de direccionamiento indirecto usando rectypes. http://www.ffconsultancy.com/languages/ray_tracer/code/1/ray.ml –

Respuesta

7

También puede hacer algo como

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

para crear un tipo de llamada a través del cual realizar la recursividad. Ahora esto funciona:

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

También me interesaría si funciona la versión más general: 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) 

Creo que se necesita un tipo con nombre que se puede representar directamente en CLI para romper la recursividad, por lo que en F # esto significa que debe escribir un delegado real también.

3

Los tipos de registros recursivos deberían funcionar también.

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

Me gustaría una aplicación práctica. O incluso uno impráctico :)

Cuestiones relacionadas