2013-03-08 9 views
8

Sto cercando di capire le classi in Haskell. Ho scritto poche sciocche code di codice per farcela. Ho scritto una classe chiamata Slang che ha una funzione. Quando trasformo Integer in un'istanza della mia classe, funziona perfettamente. Ma quando creo String un'istanza della mia classe non verrà compilata. Sono stato irrequieto con il programma in base a ciò che l'output dell'errore mi dice, ma senza risultato. Ho idea del perché funziona ...Impossibile rendere a String un'istanza di una classe in Haskell

ecco il codice seguito da l'errore:

module Practice where 

class Slang s where 
    slangify :: s -> String 

instance Slang Integer where 
    slangify int = "yo" 

instance Slang String where -- When I take this segment out, it works fine 
    slangify str = "bro" 

ERRORE:

Prelude> :load Practice 
[1 of 1] Compiling Practice   (Practice.hs, interpreted) 

Practice.hs:9:10: 
    Illegal instance declaration for `Slang String' 
     (All instance types must be of the form (T t1 ... tn) 
     where T is not a synonym. 
     Use -XTypeSynonymInstances if you want to disable this.) 
    In the instance declaration for `Slang String' 
Failed, modules loaded: none. 
Prelude> 
+0

Sì hai ragione !! Scusa, l'ho risolto – CodyBugstein

risposta

12

Il problema è che String non è un tipo di base come Integer . Quello che si sta cercando di fare è in realtà

instance Slang [Char] where 
    slangify str = "bro" 

Tuttavia, Haskell98 vieta questo tipo di typeclass al fine di mantenere le cose semplici e per rendere più difficile per le persone a scrivere le istanze che si sovrappongono come

instance Slang [a] where 
    -- Strings would also fit this definition. 
    slangify list = "some list" 

In ogni caso, come suggerisce il messaggio di errore, è possibile aggirare questa restrizione abilitando l'estensione FlexibleInstances.

+3

Plug sfortunato per un vecchio post sul blog che ho scritto esplorando come il preludio aggira questa limitazione [in Show] (http://brandon.si/code/how-the-haskell-prelude-avoids-overlapping- tipi-in-mostra /). – jberryman

+1

@jberryman: fantastico. Non mi ero fermato a pensarci. – hugomg

+0

Come abilitare FlexibleInstances? – CodyBugstein

5

Ho fatto qualche ricerca nella mia letteratura Haskell (aka la mia Bibbia corrente) e ho trovato un esempio che risolve efficacemente il mio problema.

In sostanza, in questa soluzione si imposta Char ad essere un'istanza della classe (nell'esempio del libro si chiama Visible) e quindi è possibile impostare [chars] aka una stringa, ad essere un'istanza della classe così solo con il stipula che la variabile di tipo chars sia un'istanza di "Visibile". E 'più facile capire se si guarda il codice qui sotto:

module Practice where 

class Visible a where 
    toString :: a -> String 
    size :: a -> Int 

instance Visible Char where 
    toString ch = [ch] 
    size _ = 1 

instance Visible a => Visible [a] where 
    toString = concat . map toString 
    size = foldr (+) 1 . map size 

mio GHCi carico e la funzione di chiamata:

*Practice> :l Practice 
[1 of 1] Compiling Practice   (Practice.hs, interpreted) 
Ok, modules loaded: Practice. 
*Practice> size "I love Stack!" 
14 
*Practice> 

Eureka!

Problemi correlati