Powiedzmy, że mam następujący rekord ADT:
data Foo = Bar { a :: Integer, b :: String, c :: String }
Chcę funkcji, która pobiera rekord i zwraca rekord (tego samego typu), w którym wszystkie pola oprócz jednego mają identyczne wartości, jak te przekazane jako argument, na przykład:
walkDuck x = Bar { a = a x, b = b x, c = lemonadeStand (a x) (b x) }
Powyższe działa, ale dla rekordu z większą liczbą pól (powiedzmy 10
), stworzenie takiej funkcji wymagałoby dużo pisania, które uważam za zupełnie niepotrzebne.
Czy są jakieś mniej żmudne sposoby na zrobienie tego samego?
Odpowiedzi:
Tak, istnieje fajny sposób aktualizowania pól rekordów. W GHCi możesz -
źródło
RecordWildCards
Rozszerzenie może być miłe, jak również, aby „rozpakować” pól w zakresie. Jeśli chodzi o aktualizacje, nie jest to jednak tak przyjemne:incrementA x@Foo{..} = x { a = succ a }
updateFoo x = x.{ c = "Goodbye" }
(zwróć uwagę na.
operator).To dobra praca dla soczewek :
Następnie:
zaktualizowałoby pole „c” z „test” do twojego ciągu.
źródło
test $ c .~ "Goodbye"
jaklens
by to zrobić iirc. Nie mówię, że jest to nietrwałe, ale kiedy już znasz operatorów, spodziewam się, że przyjdzie to równie łatwo, jak$
.Nie musisz definiować funkcji pomocniczych ani używać soczewek. Standardowy Haskell ma już to, czego potrzebujesz. Weźmy przykład Dona Stewarta:
Następnie możesz po prostu powiedzieć,
test { c = "Goodbye" }
aby uzyskać zaktualizowany rekord.źródło