2010-03-27 11 views
6

Diciamo che ho il seguente:"Sottoclasse" mostra in Haskell?

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

voglio usare la proiezione di default di tutti gli elementi tranne Beta, che voglio dire "due".

Posso fare questo?

+9

Non risposta: 'myShow Beta =" Due "; myShow z = show z' – kennytm

+0

Questa non è una non risposta. Questa è un'ottima risposta. :-) – Martijn

risposta

3

Per quanto ne so, non è possibile. Il meccanismo derivante non supporta comunque l'alterazione o l'estensione delle istanze derivate.

17

deriving Show utilizza il meccanismo di istanziazione standard (semplicemente restituendo la definizione). Se si desidera che qualsiasi cose particolari, si dovrà istanziare manualmente:

data Greek = Alpha | Beta | Gamma | Phi 

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

Non che questo è del tutto soddisfacente, ma si poteva fare:

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

showGreek Beta = "2" 
showGreek x = show x 

E utilizzare showGreek al posto di spettacolo. Se avete bisogno di un'istanza di vero e proprio spettacolo (nel mio codice trovo che ho bisogno di questo a meno di principianti tendono a pensare), si potrebbe fare il piuttosto ingombrante:

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

Se fosse il mio codice, che avevo appena bastone con showGreek.

Una buona regola empirica che utilizzo è che le istanze Mostra e Lettura sono generate solo da Haskell. Se show non produce codice Haskell valido, non dovrebbe essere in un'istanza Show.

+4

Non è corretto. Show non ha lo scopo di produrre codice Haskell, ma ha lo scopo di restituire una rappresentazione di stringa di un dato tipo di dati. In questo contesto, fintanto che Show and Read funzionano correttamente tra loro, non c'è davvero alcun problema a definire qualsiasi cosa si desideri. Anche l'uso di una nuova funzione 'showGreek' non è di grande aiuto, poiché l'istanziazione ha lo scopo di fornire un livello astratto con cui tutti i tipi di dati possono lavorare. – poke

+1

poke, sarei più propenso ad accettare il tuo reclamo sull'intenzione di Show se volessi fornire un riferimento. Per quanto riguarda il livello di astrazione, sei corretto. Non puoi 'showGreek' con funzioni che accettano un vincolo come Mostra a =>, solo quelli che accettano un HOF per la visualizzazione. Tuttavia, nella mia pratica, che ammetto non è uguale al tuo, è meno problematico di quanto sembri.Se ci si imbatte in esso, "Greek" dovrebbe fare. E se non accetti la soluzione "greca", allora suppongo che dovrai accettare questo come una limitazione di Haskell o passare ad un'altra lingua :-P. – luqui

+0

'base' contiene alcune istanze' Show' che non producono codice Haskell valido (come 'StdGen'). Generalmente è una buona idea far sì che 'show' produca un codice Haskell valido, ma non è obbligatorio. –

4

Alcuni degli altri suggerimenti funzionano bene nel tuo esempio particolare e suggerirei di utilizzarli.

Ma in un caso più generale, è possibile utilizzare datatype-generic programming.

Utilizzando la programmazione generica, è possibile scrivere funzioni che funzionano su più tipi di dati, ovvero funzioni che fanno lo stesso per ogni tipo di dati. Esempi di tali funzioni sono show e == (questo è il motivo per cui questi possono essere derivati ​​in GHC).

Questo è un esempio che utilizza la libreria 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 

Per essere onesti, non mi piace molto l'uscita dal Regolari show funzione (si getta in un ulteriore set di parentesi). Ma questo potrebbe essere un buon punto di partenza per scrivere le tue funzioni generiche.