Capisco perché vuoi farlo, ma sfortunatamente può essere solo un'illusione che le lezioni Haskell sembrino "aperte" nel modo in cui dici. Molte persone pensano che la possibilità di farlo sia un bug nelle specifiche Haskell, per ragioni che spiegherò di seguito. Ad ogni modo, se davvero non è appropriato per l'istanza devi essere dichiarato o nel modulo in cui viene dichiarata la classe o nel modulo in cui viene dichiarato il tipo, questo è probabilmente un segno che dovresti usare un newtype
o qualche altro wrapper intorno al tuo tipo.
I motivi per cui le istanze orfane devono essere evitate sono molto più profondi della comodità del compilatore. Questo argomento è piuttosto controverso, come puoi vedere da altre risposte. Per bilanciare la discussione, spiegherò il punto di vista secondo cui non si dovrebbero mai, mai scrivere istanze orfane, che penso sia l'opinione della maggioranza tra gli Haskeller esperti. La mia opinione è da qualche parte nel mezzo, che spiegherò alla fine.
Il problema deriva dal fatto che quando esiste più di una dichiarazione di istanza per la stessa classe e tipo, non esiste alcun meccanismo nello standard Haskell per specificare quale utilizzare. Piuttosto, il programma viene rifiutato dal compilatore.
L'effetto più semplice è che potresti avere un programma perfettamente funzionante che interromperà improvvisamente la compilazione a causa di un cambiamento che qualcun altro fa in una dipendenza lontana del tuo modulo.
Ancora peggio, è possibile che un programma funzionante inizi a bloccarsi in fase di esecuzione a causa di un cambiamento lontano. Potresti usare un metodo che presumi provenga da una certa dichiarazione di istanza e potrebbe essere silenziosamente sostituito da un'istanza diversa che è abbastanza diversa da far sì che il tuo programma inizi a bloccarsi in modo inspiegabile.
Le persone che vogliono garanzie che questi problemi non si verifichino mai loro devono seguire la regola che se qualcuno, ovunque, ha mai dichiarato un'istanza di una certa classe per un certo tipo, nessun'altra istanza deve mai essere dichiarata di nuovo in nessun programma scritto da chiunque. Ovviamente, c'è la soluzione alternativa di utilizzare a newtype
per dichiarare una nuova istanza, ma questo è sempre almeno un inconveniente minore, e talvolta anche grave. Quindi, in questo senso, coloro che scrivono intenzionalmente istanze orfane sono piuttosto scortesi.
Allora cosa si dovrebbe fare per risolvere questo problema? Il campo anti-istanze orfane afferma che l'avviso GHC è un bug, deve essere un errore che rifiuta qualsiasi tentativo di dichiarare un'istanza orfana. Nel frattempo, dobbiamo esercitare l'autodisciplina ed evitarli a tutti i costi.
Come hai visto, ci sono quelli che non sono così preoccupati per questi potenziali problemi. In realtà incoraggiano l'uso di istanze orfane come strumento per la separazione delle preoccupazioni, come suggerisci, e affermano che si dovrebbe solo assicurarsi caso per caso che non ci siano problemi. Sono stato infastidito abbastanza volte dalle istanze orfane di altre persone per convincermi che questo atteggiamento è troppo sprezzante.
Penso che la soluzione giusta sarebbe aggiungere un'estensione al meccanismo di importazione di Haskell che controllerebbe l'importazione delle istanze. Ciò non risolverebbe completamente i problemi, ma fornirebbe un aiuto per proteggere i nostri programmi dai danni delle istanze orfane che già esistono nel mondo. E poi, con il tempo, potrei convincermi che in alcuni casi limitati, forse un'istanza orfana potrebbe non essere così grave. (E proprio quella tentazione è la ragione per cui alcuni nel campo anti-orfani si oppongono alla mia proposta.)
La mia conclusione da tutto ciò è che, almeno per il momento, ti consiglio caldamente di evitare di dichiarare casi orfani, di essere rispettoso degli altri se non per altro. Usa un file newtype
.