Haskell non ha la notazione a punti per i membri del record. Per ogni membro del record, un compilatore crea una funzione con lo stesso nome con un tipo RecType -> FieldType. Ciò porta a denominare i conflitti. Ci sono modi per ovviare a questo, ad esempio, come posso avere più record con gli stessi nomi di campo?Conflitti di nomi nei record Haskell
risposta
Un altro modo per evitare questo problema è utilizzare il pacchetto lens. Esso fornisce una funzione template Haskell makeFields, che può essere utilizzato in questo modo:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeSynonymInstances #-}
import Control.Lens
data A = A
{ _aText :: String
}
makeFields ''A -- Creates a lens x for each record accessor with the name _aX
data B = B
{ _bText :: Int
, _bValue :: Int
}
-- Creates a lens x for each record accessor with the name _bX
makeFields ''B
main = do
let a = A "hello"
let b = B 42 1
-- (^.) is a function of lens which accesses a field (text) of some value (a)
putStrLn $ "Text of a: " ++ a ^. text
putStrLn $ "Text of b: " ++ show (b ^. text)
Se non si desidera utilizzare TemplateHaskell e l'obiettivo, si può anche fare manualmente quello lente di automatizzare utilizzando TemplateHaskell:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeSynonymInstances #-}
data A = A
{ aText :: String
}
data B = B
{ bText :: Int
, bValue :: Int
}
-- A class for types a that have a "text" field of type t
class HasText a t | a -> t where
-- An accessor for the text value
text :: a -> t
-- Make our two types instances of those
instance HasText A String where text = aText
instance HasText B Int where text = bText
main = do
let a = A "hello"
let b = B 42 1
putStrLn $ "Text of a: " ++ text a
putStrLn $ "Text of b: " ++ show (text b)
Ma posso davvero raccomandare l'apprendimento dell'obiettivo, in quanto fornisce anche molte altre utilità, come la modifica o l'impostazione di un campo.
Questo non funziona se due campi hanno lo stesso nome ma tipi diversi. –
@GabrielGonzalez Almeno la versione dell'obiettivo funziona per diversi tipi. Non volevo complicare la versione manuale con famiglie di tipi o dipendenze funzionali, quindi ho omesso la diversa tipologia. – bennofs
Ok, in realtà, non è così difficile, quindi ho aggiunto il supporto per diversi tipi. – bennofs
Per i progetti di grandi dimensioni, preferisco mantenere ciascun tipo nel proprio modulo e utilizzare il sistema di moduli di Haskell per gli accessori dello spazio dei nomi per ogni tipo.
Ad esempio, potrei avere qualche tipo A
nel modulo A
:
-- A.hs
data A = A
{ field1 :: String
, field2 :: Double
}
... e un altro tipo B
con campi denominato allo stesso modo in modulo B
:
-- B.hs
data B = B
{ field1 :: Char
, field2 :: Int
}
Poi se io voglio usare entrambi i tipi in qualche altro modulo C
Posso importarli qualificati per distinguere quale accessor intendo:
Sfortunatamente, Haskell non ha un modo per definire più spazi nome all'interno dello stesso modulo, altrimenti sarebbe necessario suddividere ciascun tipo in un modulo separato per farlo.
Funziona, ma è davvero brutto e prolisso. –
Questo è così imbarazzante, a volte vorrei che Haskell supportasse i moduli annidati ... – MathematicalOrchid
@MathematicalOrchid Non è così imbarazzante. In realtà questo approccio è piuttosto comune in altre lingue, ad esempio, in Java ogni tipo (classe o interfaccia) deve trovarsi in un file separato. –
Si noti che gli sviluppatori di GHC sembrano avere un piano su come gestire questo problema in futuro. Controlla this plan, che ho trovato menzionato alla fine di this blog post.
- 1. Come evitare conflitti di nomi nei sottoprogetti cmake?
- 2. Haskell gtk Tipo di installazione conflitti
- 3. Evitare conflitti di unione nei file resx
- 4. Come evitare conflitti di nome nei widget JavaScript
- 5. Come controllare l'esportazione dei record in Haskell?
- 6. Ottieni i nomi dei campi di un record Haskell come un elenco di stringhe?
- 7. Correzione dell'errore nei nomi
- 8. Riassumi un elenco di record Haskell
- 9. Come evitare conflitti di nomi durante la composizione degli oggetti
- 10. Haskell che introspecting i nomi dei campi di un record e tipi
- 11. Unione di due/tre record nei binari
- 12. Un modo migliore di inserire le directory nei moduli Haskell
- 13. Come si risolvono i conflitti di namespace nei miei pacchetti Python con i nomi dei pacchetti di libreria standard?
- 14. _Underscores nei nomi delle funzioni
- 15. Come far fronte allo spazio dei nomi Haskell?
- 16. Trovare lacune (record mancanti) nei record del database utilizzando SQL
- 17. Perché GHC Haskell non supporta i nomi dei parametri dei record sovraccaricati?
- 18. '/' nei nomi di file HDF5 confusione
- 19. Caratteri consentiti nei nomi di funzioni Python
- 20. Denominazione dei conflitti tra i valori dei campi e l'ambito locale in Haskell
- 21. Haskell record syntax e type classes
- 22. Utilizzando derivanti generico con un record Haskell
- 23. Haskell: Aggiornamento record per tipi esistenziali
- 24. Che cosa significa in genere quando un accessore di record Haskell conduce con un trattino basso?
- 25. Spark: ordina i record nei gruppi?
- 26. Delphi - Informazioni RTTI sui metodi nei record
- 27. Selettori di record nelle classi di tipi Haskell
- 28. I conflitti tra nomi dei membri e nomi argomento del costruttore
- 29. Come organizzare i file nei programmi Haskell?
- 30. trovato il numero di conflitti/elenco di conflitti nella cartella di lavoro
Cfr. http://stackoverflow.com/questions/5775068/modeling-domain-data-in-haskell/5777042#5777042 – luqui
http://stackoverflow.com/questions/6922437/ e: http://stackoverflow.com/questions/6677834/ –
Questo problema potrebbe essere risolto Presto presto in GHC. Penso che sia un progetto GSoC: D – jozefg