2012-04-14 12 views
13

Estoy definiendo un analizador sintáctico/reactivo monádico. Esto se comporta de manera bastante diferente a un analizador normal, ya que es una consulta continua. El tipo subyacente es:Propósito de una unión discriminada de un solo caso

IObservable<'a> -> IObservable<'b> 

De su análisis de varias implementaciones de analizadores en los lenguajes funcionales, parece como si el camino más apropiado para definir las cosas es un solo caso unión discriminado:

type Pattern<'a,'b> = Pattern of (IObservable<'a> -> IObservable<'b>) 

Lo cual significa entonces tienen que extraer la función subyacente utilizarlo:

let find (Pattern p) = p 

la pregunta es: ¿es sólo por convención, o con fines de extensión posterior, o es el ¿Hay una razón para hacer esto incluso si la definición nunca cambia?

Bono pregunta: Si es sólo para una firma de tipo más conveniente, ¿por qué no usar un tipo de alias:

type Pattern<'a,'b> = IObservable<'a> -> IObservable<'b> 

He avanzado bastante camino a través de esto, y no he encontrado un caso en el que la capacidad de compilación se ve afectada al no usar el DU.

Respuesta

14

F # compilador no conserva información sobre el tipo de abreviatura, por lo que no se beneficia de la inferencia de tipos en absoluto. La firma del tipo se puede entender como la especificación del programa; Permitir que el verificador de tipos haga su trabajo es una buena forma de garantizar la corrección de sus programas.

Usted necesita especificar explícitamente tipo de anotación en todas partes en el caso del tipo de alias:

type Vector = float * float 

// val add : float * float -> float * float -> Vector 
let add ((x1, y1): Vector) ((x2, y2): Vector): Vector = (x1 + y1, x2 + y2) 

pero no le da la transparencia como el uso de los UD:

type Vector = V of float * float 

// val add : Vector -> Vector -> Vector 
let add (V(x1, y1)) (V(x2, y2)) = V(x1 + y1, x2 + y2) 

En programas complejos firmas de tipos claros de hecho, es más fácil mantener la capacidad de compilación.

No solo es más fácil agregar más estuches a DU de un solo caso, sino que también es más fácil extender los DU con los métodos miembro y estático. Un ejemplo es que a menudo sobrescribe ToString() para una impresión bonita.

+0

Gracias, esa es en realidad una razón bastante concreta. Definitivamente no quiero escribir 'IObservable <'a> -> IObservable <'b>' en todas partes en lugar de 'Patrón <'a,'b>'. – yamen

+1

Un seguimiento de muchas lunas más tarde. Terminé agregando un segundo caso a la unión, y así el universo está en equilibrio. – yamen

0

Por lo que entiendo, el tipo de unión discriminada por un solo caso está ahí para proporcionar un nombre semánticamente relevante para su dominio de problema, a un tipo de backend de uso general cuyo nombre es 'cadena'.

Es un arreglo de fugas de luz para la abstracción semántica, y sólo eso, que yo sepa

+0

No creo que sea cierto. Eso es un tipo de alias. Una unión de un solo caso discriminado es una clase completa, y en este caso está envolviendo una función (o delegado en C# talk). – yamen

+0

de hecho. pero no conozco otro uso que eso ... también, tenga en cuenta que puede agregar algunos métodos a los tipos de unión. – nicolas

Cuestiones relacionadas