{-# LANGUAGE ExplicitForAll #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UnicodeSyntax #-}
{-# LANGUAGE TypeApplications #-}
module Data.Enum.Memo
(
memoize
, memoize2
, memoize3
, memoize4
, memoize5
) where
import Prelude hiding (lookup)
import Data.Array ((!), array)
memoize :: ∀ k v. (Bounded k, Enum k) => (k -> v) -> k -> v
memoize f = case array bounds vals of
memo -> \k -> memo ! fromEnum k
where
bounds = (fromEnum @k minBound, fromEnum @k maxBound)
vals = [(fromEnum k, f k) | k <- [minBound..maxBound]]
memoize2 :: ∀ k1 k2 v.
( Bounded k1, Enum k1
, Bounded k2, Enum k2
)
=> (k1 -> k2 -> v) -> k1 -> k2 -> v
memoize2 f = case array bounds vals of
memo -> \k1 k2 -> memo !
( fromEnum k1
, fromEnum k2
)
where
bounds = ( ( fromEnum @k1 minBound
, fromEnum @k2 minBound
)
, ( fromEnum @k1 maxBound
, fromEnum @k2 maxBound
)
)
vals = [( ( fromEnum k1
, fromEnum k2
)
, f k1 k2
) | k1 <- [minBound..maxBound]
, k2 <- [minBound..maxBound]]
memoize3 :: ∀ k1 k2 k3 v.
( Bounded k1, Enum k1
, Bounded k2, Enum k2
, Bounded k3, Enum k3
)
=> (k1 -> k2 -> k3 -> v) -> k1 -> k2 -> k3 -> v
memoize3 f = case array bounds vals of
memo -> \k1 k2 k3 -> memo !
( fromEnum k1
, fromEnum k2
, fromEnum k3
)
where
bounds = ( ( fromEnum @k1 minBound
, fromEnum @k2 minBound
, fromEnum @k3 minBound
)
, ( fromEnum @k1 maxBound
, fromEnum @k2 maxBound
, fromEnum @k3 maxBound
)
)
vals = [( ( fromEnum k1
, fromEnum k2
, fromEnum k3
)
, f k1 k2 k3
) | k1 <- [minBound..maxBound]
, k2 <- [minBound..maxBound]
, k3 <- [minBound..maxBound]]
memoize4 :: ∀ k1 k2 k3 k4 v.
( Bounded k1, Enum k1
, Bounded k2, Enum k2
, Bounded k3, Enum k3
, Bounded k4, Enum k4
)
=> (k1 -> k2 -> k3 -> k4 -> v) -> k1 -> k2 -> k3 -> k4 -> v
memoize4 f = case array bounds vals of
memo -> \k1 k2 k3 k4 -> memo !
( fromEnum k1
, fromEnum k2
, fromEnum k3
, fromEnum k4
)
where
bounds = ( ( fromEnum @k1 minBound
, fromEnum @k2 minBound
, fromEnum @k3 minBound
, fromEnum @k4 minBound
)
, ( fromEnum @k1 maxBound
, fromEnum @k2 maxBound
, fromEnum @k3 maxBound
, fromEnum @k4 maxBound
)
)
vals = [( ( fromEnum k1
, fromEnum k2
, fromEnum k3
, fromEnum k4
)
, f k1 k2 k3 k4
) | k1 <- [minBound..maxBound]
, k2 <- [minBound..maxBound]
, k3 <- [minBound..maxBound]
, k4 <- [minBound..maxBound]]
memoize5 :: ∀ k1 k2 k3 k4 k5 v.
( Bounded k1, Enum k1
, Bounded k2, Enum k2
, Bounded k3, Enum k3
, Bounded k4, Enum k4
, Bounded k5, Enum k5
)
=> (k1 -> k2 -> k3 -> k4 -> k5 -> v) -> k1 -> k2 -> k3 -> k4 -> k5 -> v
memoize5 f = case array bounds vals of
memo -> \k1 k2 k3 k4 k5 -> memo !
( fromEnum k1
, fromEnum k2
, fromEnum k3
, fromEnum k4
, fromEnum k5
)
where
bounds = ( ( fromEnum @k1 minBound
, fromEnum @k2 minBound
, fromEnum @k3 minBound
, fromEnum @k4 minBound
, fromEnum @k5 minBound
)
, ( fromEnum @k1 maxBound
, fromEnum @k2 maxBound
, fromEnum @k3 maxBound
, fromEnum @k4 maxBound
, fromEnum @k5 maxBound
)
)
vals = [( ( fromEnum k1
, fromEnum k2
, fromEnum k3
, fromEnum k4
, fromEnum k5
)
, f k1 k2 k3 k4 k5
) | k1 <- [minBound..maxBound]
, k2 <- [minBound..maxBound]
, k3 <- [minBound..maxBound]
, k4 <- [minBound..maxBound]
, k5 <- [minBound..maxBound]]