2012-03-19 19 views
16

Si quiero declarar una newtype tal que tipo de tipo de valor está limitado a tener una instancia para una clase de tipo, parece como si pudiera hacer eso con:newtype con RankNTypes

{-# LANGUAGE RankNTypes #-} 

newtype ShowBox = ShowBox (forall a. Show a => a) 

compila GHC que muy bien, pero cuando intento y, de hecho utilizo ShowBox con

ShowBox "hello" 

consigo un error del compilador

<interactive>:1:18: 
    Could not deduce (a ~ [Char]) 
    from the context (Show a) 
     bound by a type expected by the context: Show a => a 
     at <interactive>:1:10-24 
     `a' is a rigid type variable bound by 
      a type expected by the context: Show a => a at <interactive>:1:10 
    In the first argument of `ShowBox', namely `"hello"' 
    In the expression: ShowBox "hello" 
    In an equation for `a': a = ShowBox "hello" 

¿Hay alguna manera de hacer que esto funcione?

+0

¿Significa esta cuantificación lo que usted piensa que significa? Realmente no estoy seguro, yo mismo. Estoy pensando que _may_ significa que 'ShowBox' solo se puede aplicar a valores que son precisamente del tipo' Show a => a'. Estoy bastante interesado en ver cuál es la respuesta a esta pregunta. –

Respuesta

18

Está prometiendo al compilador que el valor que pone dentro de un ShowBox tendrá el tipo forall a. Show a => a. Solo hay un valor posible con ese tipo, y es _|_. Creo que probablemente quieras un tipo existencial, que se ve bastante similar, pero significa algo muy diferente.

{-# LANGUAGE ExistentialQuantification #-} 

data ShowBox = forall a. Show a => ShowBox a 

Esto debe hacerse con data, en lugar de newtype. La coincidencia de patrones en el constructor es lo que hace que la instancia Mostrar alcance, en este caso. Como newtype s no tienen representación en tiempo de ejecución, no tienen lugar para almacenar el testigo polimórfico que implica la cuantificación existencial.

+3

Es decir: los valores que entran en 'ShowBox' de @ user1279710 tienen que poder ser * cualquier * instancia de' Show', pero él trató de poner una instancia * particular * de 'Show' in (pause for cambio de sujeto) El único valor de tipo 'forall a. Mostrar a => a' es '_ | _' en este caso porque la clase de tipo' Show' no incluye ningún método para construir valores del tipo de instancia, solo para consumirlos. –

+3

Sería bueno si el compilador emitiera advertencias como "declaración de datos inútiles:' Mostrar a => a': solo puede estar habitado por '_ | _'" –

+0

Ok, eso tiene sentido. Esperaba que hubiera alguna forma de hacerlo sin el boxeo, pero veo que no es realmente posible. Gracias. – purefn

7

Bueno, tu Show constructor tiene este tipo:

Show :: (forall a. Show a => a) -> ShowBox 

Usted está tratando de aplicar esta función para escribir [Char], que no es de tipo forall a. Show a => a, debido a que el a es una "variable Skolem" que sólo unificarse con otro tipo bajo reglas muy estrictas (que otros podrán explicar mejor que yo).

¿Estás seguro de que lo siguiente no es lo que deseas (módulo data vs. newtype)? ¿Por qué eligió el forall dentro del constructor?

-- Show :: Show a => a -> ShowBox 
data ShowBox = forall a. Show a => Show a 
Cuestiones relacionadas