Aby keep it simple, będę korzystać z tej contrived przykład klasę (chodzi o to, że mamy kilka drogich dane pochodzące z metod):memoization i typeclasses
class HasNumber a where
getNumber :: a -> Integer
getFactors :: a -> [Integer]
getFactors a = factor . getNumber
oczywiście możemy dokonać implementacji memoizing z tej klasy, takie jak:
data Foo = Foo {
fooName :: String,
fooNumber :: Integer,
fooFactors :: [Integer]
}
foo :: String -> Integer -> Foo
foo a n = Foo a n (factor n)
instance HasNumber Foo where
getNumber = fooNumber
getFactors = fooFactors
Ale wydaje się nieco brzydki być wymagane, aby ręcznie dodać pole „czynniki” do każdego rekordu, który będzie instancją HasNumber
. Następny pomysł:
data WithFactorMemo a = WithFactorMemo {
unWfm :: a,
wfmFactors :: [Integer]
}
withFactorMemo :: HasNumber a => a -> WithFactorMemo a
withFactorMemo a = WithFactorMemo a (getFactors a)
instance HasNumber a => HasNumber (WithFactorMemo a) where
getNumber = getNumber . unWfm
getFactors = wfmFactors
Będzie to wymagało dużo boilerplate do podnoszenia wszelkie inne operacje oryginalnego a
do WithFactorMemo a
, choć.
Czy są jakieś eleganckie rozwiązania?
Innym rozwiązaniem, o którym właśnie pomyślałem, jest uczynienie funkcji * factor * zapamiętaniem, choć byłoby to mniej praktyczne, gdyby wynikiem 'getNumber' była jakaś większa struktura danych, a (AFAIK) wpisy nigdy nie zostałyby zebrane jako śmieci (w przeciwieństwie do dwóch rozwiązań w moim pytaniu). – FunctorSalad