2009-11-29 20 views
13

¿Hay alguna manera de "levantar" una instancia de clase en Haskell fácilmente?Instancia de clase de elevación en Haskell

he estado con frecuencia la necesidad de crear, por ejemplo, casos Num para algunas clases que son sólo la estructura Num "lifting" a través del constructor de tipos como este:

data SomeType a = SomeCons a 

instance (Num a)=>Num SomeCons a where 
    (SomeCons x) + (SomeCons y) = SomeCons (x+y) 
    negate (SomeCons x) = SomeCons (negate x) 
    -- similarly for other functions. 

¿Hay una manera de evitar esto repetitivo y "levantar" esta estructura Num automáticamente? Normalmente tengo que hacer esto con Show y otras clases también cuando estaba tratando de aprender existencials y el compilador no me dejaba usar deriving(Show).

Respuesta

19

El newtype generalizado es lo que queremos aquí:

{-# LANGUAGE GeneralizedNewtypeDeriving #-} 

module Main where 

newtype SomeType a = SomeCons a deriving (Num, Show, Eq) 

main = do 
    let a = SomeCons 2 
     b = SomeCons 3 
    print $ a + b 

Salida:

*Main> main 
SomeCons 5 
+1

Hum ... ¿Por qué esto funciona con newtype pero no con los datos? –

+3

Como un newtype no puede agregar constructores o campos, simplemente vuelve a envolver un tipo existente. Esto garantiza que la extensión puede funcionar con cualquier clase, en lugar de solo las clases que normalmente puede derivar para cualquier tipo de datos. – Martijn

5

GHC implementa lo que desea: Extensions to the deriving mecanism. Estas modificaciones son a menudo muestran para una futura extensión del lenguaje estándar (como se ve en haskell' wiki)

Para habilitar esta extensión, se debe usar la siguiente pragma

{-# GeneralizedNewtypeDeriving #-} 

y luego usar una deriva en su declaración newtype, como extensión habitual derivada

data SomeType a = SomeCons a deriving (Num) 
1

GeneralizedNewtypeDeriving

Cuestiones relacionadas