2012-01-16 15 views
8

Devo definire una classe di tipo Truthy che contiene un metodo true che converte un'istanza della classe di tipo in un valore Bool.Come scrivere un'istanza per tutti i tipi in un'altra classe di tipi?

mio tipo dichiarazione di classe:

class Truthy a where 
    true :: a -> Bool 

Avanti, devo definire istanze di questa classe di vari tipi, tra cui lista e tipi numerici. L'ho fatto per le liste e Int s, ma c'è un modo per farlo per tutti i tipi numerici contemporaneamente?

Sulla base della mia dichiarazione Int:

instance Truthy Int where 
    true = (/=) 0 

Ho provato ad aggiungere vincolo tipo di classe, ma non funziona:

instance (Num a) => (Truthy a) where 
    true = (/=) 0::a 

Se c'è un modo per farlo simile a quello che aveva in mente, o dovrei semplicemente definirlo separatamente per ciascun tipo numerico?

+0

"o dovrei semplicemente definirlo separatamente per ciascun tipo numerico?" - in una parola ** Sì **. L'obiettivo di progettazione delle classi di tipi è consentire l'overloading per ogni tipo. Con le estensioni può essere possibile definire istanze "overreaching" ma di solito sono un difetto di progettazione. –

+0

possibile duplicato di [Dichiarare tutte le istanze di un typeclass in un'altra classe di caratteri senza modificare le dichiarazioni di classe originali] (http: // stackoverflow.it/questions/8461029/declare-all-instances-of-a-typeclass-are-in-another-typeclass-senza-modifica) –

risposta

10

Questo potrebbe non essere di aiuto per i compiti, ma in realtà può scrivere una dichiarazione del genere. Devi solo abilitare -XFlexibleInstances per farlo. Almeno in GHC, è possibile farlo mettendo un pragma nella parte superiore del file:

{-# LANGUAGE FlexibleInstances #-} 

Se si guarda attentamente il messaggio di errore che hai, che ha detto qualcosa come "Usare -XFlexibleInstances se si desidera disabilitare questo. ".

In questo caso particolare, si sarebbe anche necessario attivare UndecideableInstances e OverlappingInstances:

{-# LANGUAGE FlexibleInstances, UndecideableInstances, OverlappingInstances #-} 

È necessario FlexibleInstances perché standard di Haskell non consente le istanze in qualsiasi forma in cui la variabile di tipo appare più di una volta in testa . Questo è completamente soddisfacente - io è una delle estensioni più comuni utilizzate (come da this question).

È necessario UndecideableInstances in quanto la dichiarazione dell'istanza potrebbe potenzialmente causare il ciclo continuo del controllo di tipo. Penso che l'uso di UndecideableInstances prevenga questo limitando quanto profondamente controllerà quando si tenta di ridurre l'istanza. Questo di solito è - anche in questo caso - ammenda, ma potrebbe teoricamente stabilire se un determinato programma supera i controlli di tipo dipendente dall'implementazione. Tuttavia, dovrebbe funzionare nel tuo caso.

Come Hammar ha sottolineato, è necessario attivare OverlappingInstances perché il "contesto" dell'istanza è ignorato al momento della verifica si sovrappongono. Il contesto è il Num a bit in questo caso. Quindi le istanze - per verificare se si sovrappongono - vengono lette come instance Truthy a... e si sovrappongono a tutto. Con OverlappingInstances abilitato, devi solo avere un'istanza che è la più specifica affinché funzioni.

+0

L'ho visto nel log degli errori. Sarebbe bello avere una spiegazione sul motivo per cui ho bisogno di abilitare qualcosa in più per poterlo compilare, o almeno dove posso leggerlo. Inoltre, è l'unico modo per fare ciò che voglio? – penelope

+0

Fondamentalmente, il report Haskell 98 ha specificato che le dichiarazioni di classe devono essere "semplici". Quindi * standard * Haskell non consente lo stile che hai provato ad usare (a meno che non sia cambiato nel 2010?). Tuttavia, il codice che hai scritto è in realtà ragionevole e implementabile, quindi è supportato da GHC; la ragione per cui hai bisogno del pragma è che non è nello standard. –

+0

Per ulteriori informazioni di quelle che probabilmente vorrai, puoi leggere a riguardo nei documenti [qui] (http://www.haskell.org/ghc/docs/7.0.1/html/users_guide/type-class-extensions.html # superclass-rules) e [here] (http://www.haskell.org/ghc/docs/7.0.1/html/users_guide/other-type-extensions.html#flexible-contexts). –

Problemi correlati