module Data.MemoCombinators.Class ( MemoTable(..) , Memoizable(..) ) where import qualified Data.MemoCombinators as Memo import Data.Int (Int8, Int16, Int32, Int64) import Data.Word (Word, Word8, Word16, Word32, Word64) import Data.Ratio (Ratio, numerator, denominator, (%)) import Control.Arrow ((&&&)) -- | The class of types which have complete memo tables. class MemoTable a where table :: Memo.Memo a instance MemoTable Bool where table = Memo.bool instance MemoTable Char where table = Memo.char instance MemoTable Int where table = Memo.integral instance MemoTable Int8 where table = Memo.integral instance MemoTable Int16 where table = Memo.integral instance MemoTable Int32 where table = Memo.integral instance MemoTable Int64 where table = Memo.integral instance MemoTable Integer where table = Memo.integral instance MemoTable Ordering where table = Memo.enum instance MemoTable Word where table = Memo.integral instance MemoTable Word8 where table = Memo.integral instance MemoTable Word16 where table = Memo.integral instance MemoTable Word32 where table = Memo.integral instance MemoTable Word64 where table = Memo.integral instance MemoTable () where table = Memo.unit instance (MemoTable a, MemoTable b) => MemoTable (a,b) where table = uncurry . memoize . curry instance (MemoTable a, MemoTable b, MemoTable c) => MemoTable (a,b,c) where table f = \(a,b,c) -> m a b c where m = memoize (\a b c -> f (a,b,c)) instance (MemoTable a, MemoTable b, MemoTable c, MemoTable d) => MemoTable (a,b,c,d) where table f = \(a,b,c,d) -> m a b c d where m = memoize (\a b c d -> f (a,b,c,d)) instance (MemoTable a, MemoTable b, MemoTable c, MemoTable d, MemoTable e) => MemoTable (a,b,c,d,e) where table f = \(a,b,c,d,e) -> m a b c d e where m = memoize (\a b c d e -> f (a,b,c,d,e)) instance (MemoTable a, MemoTable b, MemoTable c, MemoTable d, MemoTable e, MemoTable f) => MemoTable (a,b,c,d,e,f) where table f = \(a,b,c,d,e,f') -> m a b c d e f' where m = memoize (\a b c d e f' -> f (a,b,c,d,e,f')) instance (MemoTable a, MemoTable b, MemoTable c, MemoTable d, MemoTable e, MemoTable f, MemoTable g) => MemoTable (a,b,c,d,e,f,g) where table f = \(a,b,c,d,e,f',g) -> m a b c d e f' g where m = memoize (\a b c d e f' g -> f (a,b,c,d,e,f',g)) instance (MemoTable a, MemoTable b, MemoTable c, MemoTable d, MemoTable e, MemoTable f, MemoTable g, MemoTable h) => MemoTable (a,b,c,d,e,f,g,h) where table f = \(a,b,c,d,e,f',g,h) -> m a b c d e f' g h where m = memoize (\a b c d e f' g h -> f (a,b,c,d,e,f',g,h)) instance (MemoTable a, MemoTable b, MemoTable c, MemoTable d, MemoTable e, MemoTable f, MemoTable g, MemoTable h, MemoTable i) => MemoTable (a,b,c,d,e,f,g,h,i) where table f = \(a,b,c,d,e,f',g,h,i) -> m a b c d e f' g h i where m = memoize (\a b c d e f' g h i -> f (a,b,c,d,e,f',g,h,i)) instance (MemoTable a, MemoTable b, MemoTable c, MemoTable d, MemoTable e, MemoTable f, MemoTable g, MemoTable h, MemoTable i, MemoTable j) => MemoTable (a,b,c,d,e,f,g,h,i,j) where table f = \(a,b,c,d,e,f',g,h,i,j) -> m a b c d e f' g h i j where m = memoize (\a b c d e f' g h i j -> f (a,b,c,d,e,f',g,h,i,j)) instance (MemoTable a, MemoTable b, MemoTable c, MemoTable d, MemoTable e, MemoTable f, MemoTable g, MemoTable h, MemoTable i, MemoTable j, MemoTable k) => MemoTable (a,b,c,d,e,f,g,h,i,j,k) where table f = \(a,b,c,d,e,f',g,h,i,j,k) -> m a b c d e f' g h i j k where m = memoize (\a b c d e f' g h i j k -> f (a,b,c,d,e,f',g,h,i,j,k)) instance (MemoTable a, MemoTable b, MemoTable c, MemoTable d, MemoTable e, MemoTable f, MemoTable g, MemoTable h, MemoTable i, MemoTable j, MemoTable k, MemoTable l) => MemoTable (a,b,c,d,e,f,g,h,i,j,k,l) where table f = \(a,b,c,d,e,f',g,h,i,j,k,l) -> m a b c d e f' g h i j k l where m = memoize (\a b c d e f' g h i j k l -> f (a,b,c,d,e,f',g,h,i,j,k,l)) instance (MemoTable a, MemoTable b, MemoTable c, MemoTable d, MemoTable e, MemoTable f, MemoTable g, MemoTable h, MemoTable i, MemoTable j, MemoTable k, MemoTable l, MemoTable m) => MemoTable (a,b,c,d,e,f,g,h,i,j,k,l,m) where table f = \(a,b,c,d,e,f',g,h,i,j,k,l,m') -> m a b c d e f' g h i j k l m' where m = memoize (\a b c d e f' g h i j k l m' -> f (a,b,c,d,e,f',g,h,i,j,k,l,m')) instance (MemoTable a, MemoTable b, MemoTable c, MemoTable d, MemoTable e, MemoTable f, MemoTable g, MemoTable h, MemoTable i, MemoTable j, MemoTable k, MemoTable l, MemoTable m, MemoTable n) => MemoTable (a,b,c,d,e,f,g,h,i,j,k,l,m,n) where table f = \(a,b,c,d,e,f',g,h,i,j,k,l,m',n) -> m a b c d e f' g h i j k l m' n where m = memoize (\a b c d e f' g h i j k l m' n -> f (a,b,c,d,e,f',g,h,i,j,k,l,m',n)) instance (MemoTable a, MemoTable b, MemoTable c, MemoTable d, MemoTable e, MemoTable f, MemoTable g, MemoTable h, MemoTable i, MemoTable j, MemoTable k, MemoTable l, MemoTable m, MemoTable n, MemoTable o) => MemoTable (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o) where table f = \(a,b,c,d,e,f',g,h,i,j,k,l,m',n,o) -> m a b c d e f' g h i j k l m' n o where m = memoize (\a b c d e f' g h i j k l m' n o -> f (a,b,c,d,e,f',g,h,i,j,k,l,m',n,o)) instance (MemoTable a) => MemoTable [a] where table = Memo.list table instance (MemoTable a) => MemoTable (Maybe a) where table = Memo.maybe table instance (MemoTable a, MemoTable b) => MemoTable (Either a b) where table = Memo.either table table instance (Integral a, MemoTable a) => MemoTable (Ratio a) where table = Memo.wrap (uncurry (%)) (numerator &&& denominator) table -- | The class of functions which can be completely memoized. class Memoizable a where memoize :: a -> a instance (MemoTable a) => Memoizable (a -> b) where memoize = table