Per farla semplice, userò questa classe esempio inventato (il punto è che abbiamo alcuni dati costosi derivati da metodi):Memoizzazione e typeclasses
class HasNumber a where
getNumber :: a -> Integer
getFactors :: a -> [Integer]
getFactors a = factor . getNumber
Naturalmente, possiamo fare implementazioni memoizing di questa classe come ad esempio:
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
Ma sembra un po 'brutto per essere richiesto di aggiungere manualmente un campo di 'fattori' a qualsiasi record che sarà un esempio HasNumber
. Successivo idea:
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
Ciò richiederà un sacco di testo standard per il sollevamento tutte le altre operazioni dell'originale a
in WithFactorMemo a
, però.
Ci sono soluzioni eleganti?
Un'altra soluzione che ho appena pensato sarebbe quello di rendere la funzione * fattore * memoizing, anche se questo sarebbe meno pratico se il risultato di 'getNumber' fosse una struttura di dati più grande, e (per quanto ne so) le voci non avrebbero mai ottenere garbage collection (in contrasto con le due soluzioni nella mia domanda). – FunctorSalad