2011-11-17 19 views
7

¿Alguien sabe si hay una función en Haskell, que hace algo como esto:Convertir una cadena a un constructor de tipos en Haskell

"Int" -> Int 

"String" -> String 

"Bool" -> Bool 

decir. toma una representación de cadena de un nombre de constructor de tipo y la convierte al constructor de tipo real, tanto en una expresión como en un patrón.

edición: Mi objetivo general es el de simplificar algo como:

transExp (Add exp1 exp2) vars 
    = transExp exp1 vars ++ transExp exp2 vars ++ [IAdd] 

transExp (Sub exp1 exp2) vars 
    = transExp exp1 vars ++ transExp exp2 vars ++ [ISub] 

En un único ajuste de patrones, así que básicamente convertir Agregar o Sub en una cadena, añadir una "I" en la parte delantera, y convertir volver a un tipo.

+3

¿Esto es posible? ¿No son los tipos un concepto de tiempo de compilación? ¿Qué tipo de función tiene esa función? –

+0

No tengo idea de si esto es posible o no, supongo que tendría Type String -> a, pero realmente no estoy seguro ... – Jack

+0

Echa un vistazo a la plantilla haskell entonces. Además 'IAdd' no es un tipo, sino un constructor de tipo, que fue engañoso. – nponeccop

Respuesta

10

Hay una forma mucho mejor para refactorizar su código aquí sin ningún Haskell plantilla o travesuras reflexión simplemente uniéndose a sus Add y Sub casos en una sola:

data BinOp = Add | Sub | ... 

data Expr = ... 
      | BinOp BinOp Expr Expr 
      | ... 

transExp (BinOp op exp1 exp2) vars 
    = transExp exp1 vars ++ transExp exp2 vars ++ [transOp op] 
... 

transOp Add = IAdd 
transOp Sub = ISub 

De esta manera, estamos utilizando el tipo de datos para expresar directamente el hecho de que los operadores binarios están relacionados, y por lo tanto tienen traducciones similares. Todavía puede coincidir con el patrón en BinOp Add exp1 exp2 si desea hacer un caso especial para la adición en alguna parte.

+0

Solución maravillosa, mucho menos hacky de lo que estaba pensando. Muchas gracias :) – Jack

+0

Eso es mucho más elegante. Gracias por el recordatorio de que ayuda a reducir de nuevo y tener una vista más amplia. –

2

¿En qué contexto? Hay Template Haskell y Data.Typeable, pero para una respuesta realmente útil debe proporcionar más detalles.

0

Bueno, aquí está el problema.

"String" -> String 

Eso es un galimatías en Haskell-tierra, porque "String" es un valor, pero es un tipo String. Así que puede intentar esto:

String -> a 

Esto no hace lo que quiere. Debería aprender a leer las firmas de tipo, porque si no puede leer las firmas de tipo, va a estar muy discapacitado en Haskell. El tipo anterior significa, "Dame una cadena y puedo darte un valor de cualquier tipo que solicites". Hay una función en el preludio con esta firma, se llama error, que no es lo que quieres.

Suena como quieres algo en este sentido:

String -> TypeRep 

Lo sentimos, no hay tal función. TypeRep no instancia la clase Read.

¿Qué estás haciendo en realidad tratando de hacer aquí? Si nos dice lo que realmente está tratando de hacer, podemos ayudarlo con ese problema en lugar de tratar de ayudar con este problema.

+0

No está hablando de nombres de tipos sino de constructores de tipos. Solo quiere generar algunos valores y coincidencias de patrón de cadenas para evitar el texto repetitivo. – nponeccop

+2

@nponeccop: No es exactamente correcto rechazar una respuesta después de que la pregunta cambia. Este negocio sobre constructores es completamente nuevo. –

0

No puede hacerlo, porque las cadenas son datos de tiempo de ejecución y los tipos deben resolverse por completo en tiempo de compilación. Lo mejor que puede hacer probablemente con su ejemplo es una función de ayuda a eliminar parte de la duplicación:

helper exp1 exp2 vars op = transExp exp1 vars ++ transExp exp2 vars ++ [op] 
transExp (Add exp1 exp2) vars = helper exp1 exp2 vars IAdd 
transExp (Sub exp1 exp2) vars = helper exp1 exp2 vars ISub 

Pero esta realidad no puede ser muy útil en el largo plazo, dependiendo del número de casos que tiene.

En general, la coincidencia de patrones es algo que se ejecuta en contra de las estructuras de tipos, por lo que debe describirse en tipo de compilación contra los constructores de tipo concreto. Este es el precio que tiene que pagar por tener un sistema de tipo estático realmente sólido.

+0

Puede hacerlo con el código de Template Haskell que se ejecuta en tiempo de compilación – nponeccop

+0

De hecho, podría hacerlo, pero para el propósito afirmó que me parece demasiado exagerado. –

+0

Creo que debe conocer todas las soluciones posibles. Es una buena oportunidad para que aprenda lo que TH puede hacer. La solución de @hammar también es maravillosa. – nponeccop