Haskell nie ma notacji kropkowej dla członków rekordów. Dla każdego elementu rekordu kompilator tworzy funkcję o tej samej nazwie z typem RecType -> FieldType. Prowadzi to do konfliktów nazw. Czy są jakieś sposoby obejścia tego, tj. W jaki sposób mogę mieć kilka rekordów z tymi samymi nazwami pól?Konflikty nazw w zapisach Haskella
Odpowiedz
Innym sposobem na uniknięcie tego problemu jest użycie pakietu lens. Zapewnia makeFields funkcję szablonu Haskell, którego można użyć tak:
{-# 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)
Jeśli nie chcesz używać TemplateHaskell i obiektyw, można również zrobić ręcznie, co obiektyw automatyzuje użyciu 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)
Ale naprawdę mogę polecić soczewkę do nauki, ponieważ zapewnia również wiele innych narzędzi, takich jak modyfikowanie lub ustawianie pola.
Nie działa, jeśli dwa pola mają tę samą nazwę, ale różne typy. –
@GabrielGonzalez Przynajmniej wersja obiektywu działa dla różnych typów. Nie chciałem komplikować wersji ręcznej z rodzinami typów lub zależnościami funkcjonalnymi, więc pominąłem różne typy. – bennofs
OK, właściwie to nie jest takie trudne, więc dodałem obsługę różnych typów. – bennofs
W przypadku dużych projektów wolę utrzymywać każdy typ w jego własnym module i używać systemu modułów Haskella do akcesorów przestrzeni nazw dla każdego typu.
Na przykład, mogę mieć jakiś rodzaj A
w module A
:
-- A.hs
data A = A
{ field1 :: String
, field2 :: Double
}
... i inny rodzaj B
z podobnie nazwanych pól w module B
:
-- B.hs
data B = B
{ field1 :: Char
, field2 :: Int
}
Następnie gdybym chcę użyć obu typów w innym module C
Mogę zaimportować je kwalifikować, aby odróżnić który akcesor mam na myśli:
-- C.hs
import A as A
import B as B
f :: A -> B -> (Double, Int)
f a b = (A.field2 a, B.field2 b)
Niestety, Haskell nie ma sposobu na zdefiniowanie wielu przestrzeni nazw w tym samym module, w przeciwnym razie konieczne byłoby podzielenie każdego typu na osobny moduł, aby to zrobić.
Działa, ale jest naprawdę brzydki i gadatliwy. –
To jest takie niezręczne, czasami chciałbym, aby Haskell obsługiwał moduły zagnieżdżone ... – MathematicalOrchid
@MathematicalOrchid To nie jest takie niezręczne. W rzeczywistości takie podejście jest dość powszechne w innych językach, np. W Javie każdy typ (klasa lub interfejs) musi znajdować się w oddzielnym pliku. –
Pamiętaj, że deweloperzy GHC mają plan, jak poradzić sobie z tym problemem w przyszłości. Sprawdź this plan, którą znalazłem pod koniec this blog post.
- 1. libtool: konflikty nazw obiektów w archiwum (NETCDF + MinGW)
- 2. Tworzenie replikatora Haskella w aplikacji Haskella
- 3. Autoindentowanie Haskella w Vimie
- 4. RPM ignoruje konflikty
- 5. Konflikty nazw określone przez adnotację są w konflikcie z istniejącym, niekompatybilnym defektem ziarnowym.
- 6. mod_jk konflikty z mod_rewrite
- 7. Starsze konflikty CSS z Bootstrap - jak rozwiązać?
- 8. Problemy w systemie-typie Haskella
- 9. Interpreter Haskella/w definicje typu
- 10. Zrozumienie rekursji Haskella w funkcjach
- 11. Jak mogę rozwiązać konflikty importu w scala?
- 12. Jak rozwiązać konflikty w systemie TFS?
- 13. Jak rozwiązać konflikty git w yarn.lock
- 14. Wykryj konflikty między pakietami w R
- 15. Jak rozwiązać konflikty łączące w Mercurial (v1.0.2)?
- 16. Rozwiązuj opóźnione konflikty z SVN
- 17. Subversion szybko rozwiązać wszystkie konflikty
- 18. JsTree powoduje konflikty z jquery.validate
- 19. Konflikty w pakietach z automatycznymi modułami w Javie 9
- 20. Ukryty zakątek raportu Haskella
- 21. Styl wcięcia Haskella
- 22. Kombinacje Haskella i permutacja
- 23. Aplikacja operatora dolara Haskella
- 24. Ograniczenie typu "nie" Haskella
- 25. Funkcja funkcji Haskella
- 26. Zabicie binarki Haskella
- 27. Wewnętrzna reprezentacja list Haskella?
- 28. Zrozumienie Operatora obsady Haskella
- 29. Ukrywanie preludium Haskella, UNDO?
- 30. Funkcja odwrotna Haskella
Por. http://stackoverflow.com/questions/5775068/modeling-domain-data-in-haskell/5777042#5777042 – luqui
http://stackoverflow.com/questions/6922437/ oraz: http://stackoverflow.com/questions/6677834/ –
To może być naprawione już wkrótce w GHC. Myślę, że jest to projekt GSoC: D – jozefg