Say mam następujący zapis:Haskell dynamicznie ustawia pole rekordu na podstawie ciągu nazwy pola?
data Rec = Rec {
field1 :: Int,
field2 :: Int
}
Jak napisać funkcję:
changeField :: Rec -> String -> Int -> Rec
changeField rec fieldName value
takie, że mogę przechodzić w struny "pole1" lub "Pole2" do fieldName
argument i czy aktualizuje powiązane pole? Rozumiem, że w tym przypadku należy używać Data.Data
i Data.Typeable
, ale nie mogę wykreślić tych dwóch pakietów.
Przykładem biblioteki, którą widziałem, jest to cmdArgs. Poniżej znajduje się excerpt z delegowania blogu o tym, jak korzystać z tej biblioteki:
{-# LANGUAGE DeriveDataTypeable #-}
import System.Console.CmdArgs
data Guess = Guess {min :: Int, max :: Int, limit :: Maybe Int} deriving (Data,Typeable,Show)
main = do
x <- cmdArgs $ Guess 1 100 Nothing
print x
Teraz mamy proste wiersza polecenia parsera. Niektóre przykładowe interakcje są:
$ guess --min=10
NumberGuess {min = 10, max = 100, limit = Nothing}
Prawdopodobnie nie chcesz tego robić. Czy słyszałeś o [soczewkach] (http://stackoverflow.com/questions/5767129/lenses-fclabels-data-accessor-which-library- for-structure-access-and-mutatio)? Myślę, że jedynym sposobem na osiągnięcie tego byłoby hack polegający na parowaniu nazw pól z ich wskaźnikami argumentów i użyciem 'gmapQi' lub podobnego. (Musiałbyś dodać "wyprowadzenie (możliwe do zdobycia, dane)" do deklaracji rekordu, aby mieć jakąkolwiek nadzieję na działanie, nie można tego zrobić dla arbitralnych typów.) – ehird
Chcę to zrobić. Chciałbym utworzyć bibliotekę, w której użytkownik może dostarczyć rekord, a biblioteka może zapełnić rekord, analizując tekst. Tekst będzie zawierał odniesienia do pola w rekordzie, które chcę ustawić. – Ana
Najlepiej jest unikać powiązania implementacji tej funkcji użytkownika z wewnętrznymi szczegółami implementacji nazw pól rekordu. Po drugie zasugerowałem rozwiązanie oparte na soczewce @pat; można zautomatyzować tworzenie 'recMap' z nazw pól rekordów za pomocą szablonu Haskell. – ehird