Nevím, co přesně myslel - samo od sebe se uspořádání nezmění. Problémy mohou nastat, když máte funkci, která pracuje se dvěma množinami a obě mají jiné uspořádání, ale funkce předpokládá, že obě mají stejné (vím, že některé funkce ve standardní knihovně jsou na to ošetřeny, nevím, zda všechny).
Navíc podobná věc se mohla (nevím, zda stále může??) stát i v GHC Haskellu - viz příklad na konci http://blog.ezyang.com/2014/07/type-classes-confluence-coherence-global-uniqueness/ - a tam na to funkce nejsou připraveny.
Jojo, IMO myslel přesně tohle - a tohle je teda v GHC bug - tohle by tam jít nemělo. On to taky typechecker nebo linker chytí, ale jak je vidět, tak ne vždycky. A bohužel v GHC8 se to zkompiluje, a to i jako knihovna
Naštěstí je to hodně výjimečná situace (je potřeba se dost snažit, aby se to povedlo), a i trochu proti best practice, ale zkompilovat by se to teda nemělo. Otázka je, jestli s backpackem k tomu nemůže docházet častěji.
Pouzivat type classy k tomuto ucelu mi prijde dost neprakticke (navic ani nevim, zda to vyresi problemy s kolizemi jmen auto-generovanych lens, tipl bych, ze spis nevyresi) a jak jsem psal, na vice mistech jsem cetl, ze pouzivat je vylozene k pretezovani funkci je bad practice, tak nevim...
Tak jsem se na to podíval - je na to makro makeFields, viz
http://stackoverflow.com/questions/34617973/make-lenses-th-with-the-same-field-name-using-makeclassy. Tohle problém vyřeší a není to "bad practice"
Trochu je mi záhadou, k čemu jsou ve FP settery. Také je mi divné, že potřebuješ souřadnici X a neptáš se po Y. Funkcionalita by se pak dala schovat do modulu Vector. Nemusel by ses v tomto modulu pachtit s komponentami X a Y, prostě bys pracoval s vektory.
Lens jsou něco jako XPath, ale nad interními strukturami - které jsou v FP všechny immutable. Takž lens teda částečně řeší problém, který mimo FP nemusí řešit - tzn. modifikaci vnořených struktur. Ale z druhé strany je to neuvěřitelně flexibilní záležitost, speciálně s různým Travsersable, index lens apod. Navíc nejde jen o setter, ale je to FP - tak tam máš i "over". Tohle je trochu vycucané z prstu, ale máš třeba:
data A { _cislo :: Int, _...}
cache :: Map T.Text (Maybe A)
-- Přičti ke všem A._cislo v cache (tzn. Just hodnotám) jedničku
let res = cache & traverse . _Just . cislo %~ (+1)
Nedávno jsem řešil třeba modifikaci nějakého XMLka. Potřeboval jsem nastavit nějakou option - přidat do toho stromu na určité místo nějakou XML podstrukturu. Tohle vypadá dost hrozně..ale zkus si představit, jak bys to dělal v non-FP jazyce - tohle vypadá dost mutable díky State monadu - a "zoom" je nádstavba mimo jiné nad settery:
-- | Najde Phase konkretniho jmena
phaseWithName pname = svcPhases . traverse . phaseXml . nodes . filtered (\phase -> phase ^? tel "name" . text == Just pname)
-- | Najde konkretni option ve fazi
phaseOption optname = tel "options" . nodes . doption optname
... atd.
addMountConfig (Just (CopyMountParameters {..})) = do
zoom (phaseWithName "Recover-Copy") $ do
enabled .= "true"
phaseOption "recoveryInstance" .= Just _cpInstance
phaseOption "recoveryType" .= Just "recovery"
phaseOption "dbRenameSuffix" .= Just _cpSuffix
zoom (phaseWithName "Mount-Copy") $ do
enabled .= "true"
phaseOption "mountpath" .= Just _cpMountPath
phaseOption "copyMetadataPath" .= Just _cpMountPath
phaseOption "mounthost" .= Just _cpHost
phaseOption "accesstype" .= Just "read-write"