Jak miałem writing up an answer właśnie teraz, natknąłem się na ciekawy problem:Record Wartość domyślna Składnia akcesor
data Gender = Male | Female
deriving (Eq, Show)
data Age = Baby | Child | PreTeen | Adult
deriving (Eq, Show, Ord)
data Clothing = Pants Gender Age
| Shirt Gender Age
| Skirt Age -- assumed to be Female
deriving (Show, Eq)
Załóżmy, że chcemy napisać ostateczny typ danych ze składnią rekordu:
data Clothing = Pants {gender :: Gender, age :: Age}
| Shirt {gender :: Gender, age :: Age}
| Skirt {age :: Age}
deriving (Show, Eq)
Problem polega na tym, że chcę, aby gender $ Skirt foo
zawsze oceniał na Female
(niezależnie od foo
, który jest Age
). Mogę myśleć o kilka sposobów, aby to osiągnąć, ale wymagają one, że albo
- stosowanie inteligentnych konstruktorzy, teoretycznie umożliwiając
Skirt Male foo
ale nie narażając konstruktorów - definiować własne
gender
funkcję
Z # 1, nie ujawniając konstruktora w module, skutecznie uniemożliwiam użytkownikom modułu korzystanie z zapisu składni. Z # 2 muszę całkowicie zrezygnować ze składni lub zdefiniować dodatkową funkcję gender'
, która ponownie pokonuje składnię rekordów.
Czy istnieje sposób, aby skorzystać ze składni rekordów, a także zapewnić "domyślną", niezmienną wartość jednego z moich konstruktorów? Jestem także otwarty na rozwiązania nieopisane na składnię (może soczewki?), O ile są tak samo eleganckie (lub moreso).
Normalny obiektyw nie działałby, ponieważ można przypisać pole 'gender' z dwoma konstruktorami, ale nie drugim. Myślę, że robienie tego jest złym pomysłem; jeśli 'foo' jest rekordzistą, a' foo x' działa, to 'x {foo = y}' również powinno. – ehird
Zwykle używam wersji 2. – augustss
W jaki sposób dodanie funkcji 'gender'' (czy mogę ją nazwać' totalGender' lub 'safeGender' lub coś podobnego) powoduje uszkodzenie składni rekordów? –