Memories and Styles

To make it simple, I will use this contrived example class (the fact is that we have some expensive data obtained from methods):

class HasNumber a where
  getNumber :: a -> Integer
  getFactors :: a -> [Integer]
  getFactors a = factor . getNumber

Of course, we can memoize implementations of this class, such as:

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

But it seems a little ugly to manually add a “factors” field to any record that will be an instance HasNumber. The following 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

This will require a large number of templates for all other operations of the original ain WithFactorMemo a.

Are there any elegant solutions?

+5
source share
1 answer

: . . typeclass TC a, a , . , HasNumber :

data Number = Number {
    getNumber' :: Integer,
    getFactors' :: [Integer]
}

, :

toNumber :: (HasNumber a) => a -> Number
toNumber x = Number (getNumber x) (getFactors x)

Number, , HasNumber.

instance HasNumber Number where
    getNumber = getNumber'
    getFactors = getFactors'

, , . Number. , , , . , Foo :

data Foo = Foo {
    fooName :: String,
    fooNumber :: Number
}

, Number.

+7

All Articles