2011-09-23 20 views
8

Tengo curiosidad por qué tengo que escribir esto,explicación de "tipo ilegal de sinónimos familia"

instance (HzMonad , Data.Suitable.Suitable α, γ ~ ExprTyp α) => VarDecl γ where 
    var = varhz 

en lugar de esta

instance (HzMonad , Data.Suitable.Suitable α) => VarDecl (ExprTyp α) where 
    var = varhz 

-- error 
Hz2/Language.hs:114:53: 
    Illegal type synonym family application in instance: ExprTyp α 
    In the instance declaration for `VarDecl (ExprTyp α)' 

donde

varhz :: 
    (HzMonad , Data.Suitable.Suitable α) => 
    String -> ExprTyp α -> (ExprTyp α) 

¿Cuál es la tilde de todos modos? Muchas gracias.

+3

No tengo la energía (esta noche) para escribir una respuesta completa, pero la respuesta corta es que este es otro ejemplo de suposiciones profundamente arraigadas acerca de que las cosas a nivel de tipo que son inyectables resultan ser falsas cuando escribes las familias se agregan a la mezcla. La tilde es una afirmación de igualdad de tipo. –

+0

Ah, ahora entiendo, no hay problemas. Gracias por la nota. Cómo evitarlo es otra historia, que todavía estoy tratando de resolver. – gatoatigrado

Respuesta

2

Creo que el problema es que todo en el lado derecho de => debe ser un constructor de tipos o tipo de variable. ExprTyp podría referirse a múltiples constructores de tipo differet. Reemplazar esto con una restricción de igualdad funcionará, pero la instancia resultante será efectivamente inútil, ya que el compilador no podrá deducir nada sobre γ dado que es un ExprTyp - ExprTyp podría tener un alias para cualquier cosa.

En mi situación, estoy intentando escribir una mónada DSL, la solución es envolver todos los usos del tipo asociado en un constructor newtype. Por ejemplo, si comenzamos con,

class MyDSL m a where 
    type ExprTyp m :: * -> * 
    printE :: ExprTyp m a -> m() 

luego envolver esto se traducirá en

newtype ExprT a = ExprT a 
class MyDSL m a where 
    type ExprTyp m :: * -> * 
    printE :: ExprT (ExprTyp m a) -> m() 

Entonces, por ejemplo, las declaraciones de variables (que estaba escribiendo código para declaraciones de variables tupled) podría ser,

instance (HzMonad , Data.Suitable.Suitable α, γ ~ ExprTyp α) => VarDecl (ExprT γ) 
instance (Monad , VarDecl α, VarDecl β) => VarDecl (α, β) 

publique un comentario si algo no está claro.

Cuestiones relacionadas