sintaxis recursividad recursivas funciones estructura ejemplos datos arbol f# restriction f#-3.0

recursividad - F#cómo especificar restricción de tipo en uniones recursivas discriminadas



recursividad estructura de datos (2)

Estoy tratando de definir mi gramática como una unión discriminada. Tiene dos tipos posibles: int y datetime y operadores matemáticos de Add y Mul . Add trabajos en int y datetime (como add days in int) Mul funciona solo en int y no en datetime gramática puede ser recursiva

Mi gramática parece

type MyExpression = |Integer of int |Date of datetime |Add of MyExpression * MyExpression |Mul of MyExpression * MyExpression

He escrito un analizador (fparsec) que puede analizar texto en mi gramática, pero no estoy seguro de cómo manejar la condición de que Mul puede ser recursivo, pero solo en Integer .

¿Existe una opción para definir esta restricción en mi tipo MyExpression o tengo que manejar esto en mi entrada analizada?


El diseño sugerido por Asti también sería mi primera opción. Dependiendo de sus requisitos, eso puede ser todo lo que necesita.

Sin embargo, también te permite compilar una expresión como

Add(Val(System.Console.Out), Val(System.Console.Error))

que probablemente no es lo que quieres.

Alternativamente, podría modelar expresiones como esta:

open System type IntExpression = | Integer of int | Mul of IntExpression * IntExpression | Add of IntExpression * IntExpression type DateTimeExpression = | Date of DateTime | Add of DateTimeExpression * DateTimeExpression type MyExpression = | IntExpression of IntExpression | DateTimeExpression of DateTimeExpression

Esta es claramente una definición de tipo más detallado, pero incorpora la regla de que una expresión puede contener nodos hoja de valores enteros o DateTime , y ningún otro valor, si esa es la regla que desea aplicar.

No estoy afirmando que esto sea mejor; Solo estoy suministrando una alternativa.

Uso:

> IntExpression(Mul(IntExpression.Add(Integer(1), Integer(2)),Integer 3));; val it : MyExpression = IntExpression (Mul (Add (Integer 1,Integer 2),Integer 3)) > DateTimeExpression(Add(Date(DateTime.MinValue),Date(DateTime.MinValue)));; val it : MyExpression = DateTimeExpression (Add (Date 01.01.0001 00:00:00 {Date = 01.01.0001 00:00:00; Day = 1; DayOfWeek = Monday; DayOfYear = 1; Hour = 0; Kind = Unspecified; Millisecond = 0; Minute = 0; Month = 1; Second = 0; Ticks = 0L; TimeOfDay = 00:00:00; Year = 1;}, Date 01.01.0001 00:00:00 {Date = 01.01.0001 00:00:00; Day = 1; DayOfWeek = Monday; DayOfYear = 1; Hour = 0; Kind = Unspecified; Millisecond = 0; Minute = 0; Month = 1; Second = 0; Ticks = 0L; TimeOfDay = 00:00:00; Year = 1;}))


Si tiene restricciones basadas en tipo, puede ser más fácil ir por un enfoque genérico:

type MyExpression<''t> = |Val of ''t |Mul of MyExpression<int> * MyExpression<int> |Add of MyExpression<''t> * MyExpression<''t> let Integer (x:int) = Val(x) let Date (x:DateTime) = Val(x)

Uso:

Mul(Integer(1), Integer(2)) //compiles Mul(Date(DateTime.Now), Date(DateTime.Now)) //error