2010-03-27 26 views
6

Digamos que tengo el siguiente:¿Espectáculo de "subclases" en Haskell?

data Greek = Alpha | Beta | Gamma | Phi deriving Show 

Quiero usar la proyección por defecto de todos los elementos excepto Beta, que quiero decir "dos".

¿Puedo hacer esto?

+9

Sin respuesta: 'myShow Beta =" Two "; myShow z = show z' – kennytm

+0

Eso no es una falta de respuesta. Esa es una muy buena respuesta. :-) – Martijn

Respuesta

3

Hasta donde yo sé, no se puede. El mecanismo de derivación no admite de todos modos para alterar o extender las instancias derivadas.

17

deriving Show utiliza el mecanismo de creación de instancias estándar (simplemente devuelve la definición). Si desea cualquier cosas especiales, tendrá que crear una instancia de forma manual:

data Greek = Alpha | Beta | Gamma | Phi 

instance Show Greek 
    where 
     show Alpha = "Alpha" 
     show Beta = "2" 
     show Gamma = "Gamma" 
     show Phi = "Phi" 
7

No es que sea del todo satisfactoria, pero se podía hacer:

data Greek = Alpha | Beta | Gamma | Phi 
    deriving (Show) 

showGreek Beta = "2" 
showGreek x = show x 

Y el uso de showGreek en lugar de espectáculo. Si se necesitaba un ejemplo verdadero espectáculo (en mi código encuentro que necesito esto menos de los principiantes tienden a pensar), se puede hacer el bien engorroso:

newtype Greek' = Greek' Greek 
instance Show Greek' where 
    show (Greek' g) = showGreek g 

si se tratara de mi código, simplemente metía con showGreek.

Una buena regla de oro que uso es que las instancias de Mostrar y Leer solo se generan en Haskell. Si show no produce un código Haskell válido, no debería estar en una instancia de Show.

+4

Eso no es correcto. Show no está destinado a producir código Haskell, sino que debe devolver una representación de cadena de un tipo de datos determinado. En ese contexto, siempre y cuando Show and Read funcione correctamente entre ellos, realmente no hay problema para definir cualquier cosa que desee con él. Además, usar una nueva función 'showGreek' en realidad no ayuda, ya que la instanciación está destinada a proporcionar algún nivel abstracto con el que todos los tipos de datos puedan funcionar. – poke

+1

poke, me inclinaría más a aceptar su reclamo sobre la intención de Mostrar si proporcionara una referencia. En cuanto al nivel de abstracción, estás en lo cierto. No puede 'showGreek' con funciones que aceptan una restricción como Show a =>, solo aquellas que toman un HOF para mostrar. Aún así, en mi práctica, que admito que no es la misma que la tuya, es menos un problema de lo que parece.Si te topas con eso, 'Griego'' debería hacer. Y si no acepta la solución 'griega'', entonces supongo que tendrá que aceptar esto como una limitación de Haskell o cambiar a otro idioma :-P. – luqui

+0

'base' contiene algunas instancias' Show' que no producen código Haskell válido (como 'StdGen'). En general, es una buena idea hacer que 'show' produzca código Haskell válido, pero no es obligatorio en absoluto. –

4

Algunas de las otras sugerencias funcionan muy bien en su ejemplo particular, y sugiero usarlas.

Pero en un caso más general es posible que desee utilizar datatype-generic programming.

Mediante la programación genérica, puede escribir funciones que funcionen en múltiples tipos de datos, es decir, funciones que hagan lo mismo para cada tipo de datos. Ejemplos de tales funciones son show y == (esta es la razón por la cual pueden derivarse en GHC).

Este es un ejemplo que utiliza la biblioteca regular:

{-# LANGUAGE TemplateHaskell, EmptyDataDecls, TypeFamilies #-} 

import Generics.Regular 
import qualified Generics.Regular.Functions.Show as G 

data Greek = Alpha | Beta | Gamma | Phi 

-- These two lines are all that is needed to use 
-- Regulars generic functions on the 'Greek' data type. 
$(deriveAll ''Greek "PFGreek") 
type instance PF Greek = PFGreek 

-- Manual written instance for 'Show' 
instance Show Greek where 
    show Beta = "Two" 
    show x = G.show x -- Use Regulars 'show' for the boring parts 

Para ser honesto, no me gusta mucho la salida de Regulares show función (que lanza en un juego extra de paréntesis). Pero este podría ser un buen punto de partida para escribir sus propias funciones genéricas.