2010-07-19 15 views
14

Arrivando a Haskell da uno sfondo in vari linguaggi OO, una cosa che mi sembra un po 'un inconveniente è che i nomi di funzione e campo non sono legati ai tipi che essi sei associato, quindi è facile imbattersi in scontri se diversi tipi di dati hanno campi con lo stesso nome.Nome in conflitto tra etichette di campo di tipi di dati diversi in Haskell

Se ho questi tre moduli:

module One where 

data Foo a = Foo { value :: a } 

---- 

module Two where 

data Bar a = Bar { value :: a } 

---- 

module Three where 

import One 
import Two 

foo = Foo { value = 42 } -- compile error here 
n = value foo -- and here 

i riferimenti non qualificati a value nel modulo Three sono considerati ambigui, anche se solo uno dei due nomi importati ha senso in questo contesto. (In un linguaggio OO, i riferimenti a foo.value e bar.value sarebbe ambigua.)

Certo che posso disambiguare scrivendo Foo { One.value = 42 }, ma che sembra imbarazzante. Posso anche denominare i campi in modo diverso, ad es. "fooValue" e "barValue", ma la ridondanza in Foo { fooValue = 42 } sembra imbarazzante.

Questo è davvero un caso particolare del problema più generale delle funzioni in diversi moduli che hanno lo stesso nome ma operano su tipi diversi, non correlati. Mi sembra di imbattermi più spesso con i nomi dei campi, però. Ad esempio, ho diversi tipi di dati, non correlati da una classe di tipo ma spesso usati insieme, che contengono valori di colore, quindi mi piacerebbe che ognuno di essi avesse un campo chiamato "colore".

In che modo gli sviluppatori Haskell esperti hanno il nome delle cose e le organizzano in moduli, per evitare questo tipo di situazione?

+0

Punto minore: manca la funzione di costruzione nella definizione di "Barra". –

+0

@Travis Brown: Oops, quello era un errore di battitura. Grazie per segnalarlo. – Wyzard

risposta

9

L'estensione GHC -XDisambiguateRecordFields consentirà foo = Foo { value = 42 } (ma non n = value foo).

C'è uno large body of literature sulle carenze del sistema di record corrente di Haskell e candidati per la sua sostituzione, così come una manciata di librerie che tentano di fornire soluzioni migliori ora. fclabels è l'unico che ho usato personalmente.

This StackOverflow question è simile e alcune risposte potrebbero essere utili anche per te.

Questo è davvero un caso speciale della questione più generale delle funzioni in diversi moduli che hanno lo stesso nome ma operano su diversi tipi indipendenti.

Qualified imports e alias sono in genere sufficienti per risolvere questo problema.

1

Si può considerare una classe di tipo, se esiste una funzione di accesso comune su tutti questi tipi. Per esempio.

class Fieldable a where 
    field :: a -> b 

instance Fieldable (a,b) where 
    field = fst 

Ecc

+1

I nomi dei campi di un tipo di dati possono far parte di un'istanza di classe? Se creo un valore di classe Valued ab dove value :: a -> b', quindi associo i miei due tipi con esso, dovrei fare qualcosa come 'instance Valued (Foo a) a where value = value' e that is not valido (i due significati del conflitto 'valore'). Sembra che non possa definire una funzione come parte di un'istanza di classe se il suo nome è già stato definito in precedenza. – Wyzard

2

Come esperti sviluppatori Haskell nominare le cose, e organizzarli in moduli, per evitare questo tipo di situazione?

con cui ho lavorato solo con un paio di sviluppatori esperti Haskell, e lo fanno roba terribile come

data Foo a = Foo { foo_value :: a } 

data Bar a = Bar { bar_value :: a } 

o anche

data Apocalypse a = A { ap_value :: a } 

In generale, ho la sensazione che un sacco degli Haskellers dei vecchi tempi non amano i nomi qualificati e vogliono davvero fingere che il mondo abbia solo uno spazio di grande nome, uscito direttamente dai tempi bui. (C'è stato un tempo in cui compilatori C avevano le stesse restrizioni sui nomi di campo, che è il motivo per cui il modo in un struct stat si chiama st_mode e non semplicemente mode.)

È possibile sovraccaricare i nomi con le classi di tipo, ma gli sviluppatori esperti So che non mi piacciono le lezioni di tipo gratuito. Non riesco mai a capire quando pensano che una lezione di tipo sarà gratuita o meno.

Spero che un giorno le persone Haskell facciano i conti con uno spazio dei nomi gerarchico e inizieranno a utilizzare nomi qualificati. Come Dio intendeva.

+0

Quando non si vogliono realmente i selettori di record polimorfici, allora ha senso per me non forzarli solo per qualche piccolo vantaggio sintattico. Anche se è possibile utilizzare le cose qualificate, mi sembra che reclamare un nome comune per un campo usato raramente, specialmente uno che di solito dovrebbe essere accessibile solo attraverso una funzione di supporto, è una cattiva forma. – sclv

+0

Ho usato nomi qualificati il ​​più possibile. Il linguaggio stesso lo tratta bene; l'unico problema è che Haddock diventa molto meno utile con i nomi qualificati perché assume ancora l'unico grande spazio dei nomi. (Puoi rendere i nomi dei tipi di show di Haddock qualificati, ma continuerà a mostrare i collegamenti ipertestuali non qualificati). –

Problemi correlati