packages feed

monad-memo 0.5.0 → 0.5.1

raw patch · 10 files changed

+418/−138 lines, 10 filesdep +transformers-compatPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: transformers-compat

API changes (from Hackage documentation)

+ Control.Monad.Trans.Memo.ReaderCache: instance Control.Monad.Primitive.PrimMonad m => Control.Monad.Primitive.PrimMonad (Control.Monad.Trans.Memo.ReaderCache.ReaderCache c m)
+ Control.Monad.Trans.Memo.ReaderCache: instance Data.Array.Base.MArray (Data.Array.Base.STUArray s) e (GHC.ST.ST s) => Data.Array.Base.MArray (Data.Array.Base.STUArray s) e (Control.Monad.Trans.Memo.ReaderCache.ReaderCache c (GHC.ST.ST s))
+ Control.Monad.Trans.Memo.ReaderCache: instance Data.Array.Base.MArray (GHC.Arr.STArray s) e (Control.Monad.Trans.Memo.ReaderCache.ReaderCache c (GHC.ST.ST s))
+ Control.Monad.Trans.Memo.ReaderCache: instance Data.Array.Base.MArray Data.Array.IO.Internals.IOUArray e GHC.Types.IO => Data.Array.Base.MArray Data.Array.IO.Internals.IOUArray e (Control.Monad.Trans.Memo.ReaderCache.ReaderCache c GHC.Types.IO)
+ Control.Monad.Trans.Memo.ReaderCache: instance Data.Array.Base.MArray GHC.IOArray.IOArray e (Control.Monad.Trans.Memo.ReaderCache.ReaderCache c GHC.Types.IO)
+ Control.Monad.Trans.Memo.StateCache: instance Control.Monad.Primitive.PrimMonad m => Control.Monad.Primitive.PrimMonad (Control.Monad.Trans.Memo.StateCache.StateCache c m)
+ Control.Monad.Trans.Memo.StateCache: instance Data.Array.Base.MArray (Data.Array.Base.STUArray s) e (GHC.ST.ST s) => Data.Array.Base.MArray (Data.Array.Base.STUArray s) e (Control.Monad.Trans.Memo.StateCache.StateCache c (GHC.ST.ST s))
+ Control.Monad.Trans.Memo.StateCache: instance Data.Array.Base.MArray (GHC.Arr.STArray s) e (Control.Monad.Trans.Memo.StateCache.StateCache c (GHC.ST.ST s))
+ Control.Monad.Trans.Memo.StateCache: instance Data.Array.Base.MArray Data.Array.IO.Internals.IOUArray e GHC.Types.IO => Data.Array.Base.MArray Data.Array.IO.Internals.IOUArray e (Control.Monad.Trans.Memo.StateCache.StateCache c GHC.Types.IO)
+ Control.Monad.Trans.Memo.StateCache: instance Data.Array.Base.MArray GHC.IOArray.IOArray e (Control.Monad.Trans.Memo.StateCache.StateCache c GHC.Types.IO)
- Control.Monad.Trans.Memo.ReaderCache: evalReaderCache :: () => ReaderCache r m a -> r -> m a
+ Control.Monad.Trans.Memo.ReaderCache: evalReaderCache :: ReaderCache r m a -> r -> m a
- Control.Monad.Trans.Memo.StateCache: runStateCache :: () => StateCache s m a -> s -> m (a, s)
+ Control.Monad.Trans.Memo.StateCache: runStateCache :: StateCache s m a -> s -> m (a, s)

Files

CHANGES view
@@ -22,3 +22,7 @@ - Use `Except` instead of depricated `Error` - Remove support for `ListT` transformer since it is now depricated - Use standard `StateT` & `ReaderT` for `MonadCache` implementations++0.5.1+- Support multiple mutable caches in transformers stack+  This allows Array/Vector-based caches to be used for mutually recursive function memoization
Control/Monad/Memo/Array.hs view
@@ -50,9 +50,7 @@ import Data.Maybe (Maybe(..)) import Data.Array.ST import Data.Array.IO-import Control.Applicative import Control.Monad-import Control.Monad.Fix import Control.Monad.Trans.Class import Control.Monad.ST import System.IO@@ -102,6 +100,9 @@ type instance Array (ST s) = STArray s type instance Array IO = IOArray +type instance Array (ReaderCache c (ST s)) = STArray s+type instance Array (ReaderCache c IO) = IOArray+ -- | Memoization monad based on mutable boxed array type ArrayCache k e m = Cache (Array m) k e m @@ -141,6 +142,9 @@  type instance UArray (ST s) = STUArray s type instance UArray IO = IOUArray++type instance UArray (ReaderCache c (ST s)) = STUArray s+type instance UArray (ReaderCache c IO) = IOUArray  -- | Memoization monad based on mutable unboxed array type UArrayCache k e m = Cache (UArray m) k e m
Control/Monad/Memo/Vector/Expandable.hs view
@@ -47,9 +47,7 @@ import Data.Vector.Generic.Mutable import qualified Data.Vector.Mutable as M import qualified Data.Vector.Unboxed.Mutable as UM-import Control.Applicative import Control.Monad-import Control.Monad.Fix import Control.Monad.Trans.Class import Control.Monad.Primitive 
Control/Monad/Trans/Memo/ReaderCache.hs view
@@ -11,7 +11,8 @@  -} -{-# LANGUAGE NoImplicitPrelude, GeneralizedNewtypeDeriving #-}+{-# LANGUAGE GeneralizedNewtypeDeriving, FlexibleContexts,+    TypeFamilies, FlexibleInstances, MultiParamTypeClasses #-}  module Control.Monad.Trans.Memo.ReaderCache (@@ -22,22 +23,61 @@  ) where -import Data.Function import Control.Applicative import Control.Monad import Control.Monad.IO.Class import Control.Monad.Fix+import Control.Monad.Primitive+import Control.Monad.ST import Control.Monad.Trans.Class import Control.Monad.Trans.Reader-+import Data.Array.Base+import Data.Array.IO+import Data.Array.ST  newtype ReaderCache c m a = ReaderCache { toReaderT :: ReaderT c m a }     deriving (Functor, Applicative, Alternative, Monad, MonadPlus, MonadFix, MonadTrans, MonadIO)  {-# INLINE evalReaderCache #-}+evalReaderCache :: ReaderCache r m a -> r -> m a evalReaderCache = runReaderT . toReaderT  -- | Returns internal container container :: Monad m => ReaderCache c m c {-# INLINE container #-} container = ReaderCache ask+++instance PrimMonad m => PrimMonad (ReaderCache c m) where+  type PrimState (ReaderCache c m) = PrimState m+  primitive = lift . primitive+++instance MArray IOArray e (ReaderCache c IO) where+  getBounds = lift . getBounds+  getNumElements = lift . getNumElements+  newArray a = lift . newArray a+  unsafeRead a = lift . unsafeRead a+  unsafeWrite a i = lift . unsafeWrite a i++instance MArray IOUArray e IO => MArray IOUArray e (ReaderCache c IO) where+  getBounds = lift . getBounds+  getNumElements = lift . getNumElements+  newArray a = lift . newArray a+  unsafeRead a = lift . unsafeRead a+  unsafeWrite a i = lift . unsafeWrite a i+++instance MArray (STArray s) e (ReaderCache c (ST s)) where+  getBounds = lift . getBounds+  getNumElements = lift . getNumElements+  newArray a = lift . newArray a+  unsafeRead a = lift . unsafeRead a+  unsafeWrite a i = lift . unsafeWrite a i++instance MArray (STUArray s) e (ST s) => MArray (STUArray s) e (ReaderCache c (ST s)) where+  getBounds = lift . getBounds+  getNumElements = lift . getNumElements+  newArray a = lift . newArray a+  unsafeRead a = lift . unsafeRead a+  unsafeWrite a i = lift . unsafeWrite a i
Control/Monad/Trans/Memo/StateCache.hs view
@@ -11,7 +11,8 @@  -} -{-# LANGUAGE NoImplicitPrelude, GeneralizedNewtypeDeriving #-}+{-# LANGUAGE GeneralizedNewtypeDeriving, TypeFamilies,+  MultiParamTypeClasses, FlexibleInstances, FlexibleContexts #-}  module Control.Monad.Trans.Memo.StateCache ( @@ -22,6 +23,9 @@     evalStateCache ) where +import Control.Monad.Primitive+import Control.Monad.ST+import Data.Array.MArray import Data.Function import Control.Applicative import Control.Monad@@ -29,12 +33,17 @@ import Control.Monad.Fix import Control.Monad.Trans.Class import Control.Monad.Trans.State.Strict+import Data.Array.Base+import Data.Array.IO+import Data.Array.ST  + newtype StateCache c m a = StateCache { toStateT :: StateT c m a }     deriving (Functor, Applicative, Alternative, Monad, MonadPlus, MonadFix, MonadTrans, MonadIO)  {-# INLINE runStateCache #-}+runStateCache :: StateCache s m a -> s -> m (a, s) runStateCache = runStateT . toStateT  -- | Evaluates computation discarding the resulting container @@ -51,3 +60,38 @@ setContainer :: Monad m => c -> StateCache c m () {-# INLINE setContainer #-} setContainer = StateCache . put+++instance PrimMonad m => PrimMonad (StateCache c m) where+  type PrimState (StateCache c m) = PrimState m+  primitive = lift . primitive+++instance MArray IOArray e (StateCache c IO) where+  getBounds = lift . getBounds+  getNumElements = lift . getNumElements+  newArray a = lift . newArray a+  unsafeRead a = lift . unsafeRead a+  unsafeWrite a i = lift . unsafeWrite a i++instance MArray IOUArray e IO => MArray IOUArray e (StateCache c IO) where+  getBounds = lift . getBounds+  getNumElements = lift . getNumElements+  newArray a = lift . newArray a+  unsafeRead a = lift . unsafeRead a+  unsafeWrite a i = lift . unsafeWrite a i+++instance MArray (STArray s) e (StateCache c (ST s)) where+  getBounds = lift . getBounds+  getNumElements = lift . getNumElements+  newArray a = lift . newArray a+  unsafeRead a = lift . unsafeRead a+  unsafeWrite a i = lift . unsafeWrite a i++instance MArray (STUArray s) e (ST s) => MArray (STUArray s) e (StateCache c (ST s)) where+  getBounds = lift . getBounds+  getNumElements = lift . getNumElements+  newArray a = lift . newArray a+  unsafeRead a = lift . unsafeRead a+  unsafeWrite a i = lift . unsafeWrite a i
README.md view
@@ -1,3 +1,6 @@+# monad-memo+[![Build Status](https://travis-ci.org/EduardSergeev/monad-memo.svg?branch=master)](https://travis-ci.org/EduardSergeev/monad-memo)+ ## Purpose This package provides a convenient mechanism for adding memoization to Haskell monadic functions. 
benchmark/Main.hs view
@@ -3,12 +3,13 @@ module Main (main) where  import Data.Int-import Data.Word import Data.List+import Data.Word import qualified Data.IntMap as IM import Data.Array import Control.Monad.ST import Control.Monad.Memo+import Control.Monad.Memo.Class import Control.Monad.Memo.Vector.Unsafe import Control.Monad.Memo.Vector.Expandable import Criterion.Main@@ -18,6 +19,7 @@ --------------------  {-# INLINE fibm #-}+fibm :: (Eq k, Num k, Num v, MonadMemo k v m) => k -> m v fibm 0 = return 0 fibm 1 = return 1 fibm n = do@@ -45,29 +47,29 @@   fibIOV :: Int -> IO Word-fibIOV n = evalVectorMemo (fibm n) n+fibIOV n = evalVectorMemo (fibm n) (n+1)  fibIOUV :: Int -> IO Word-fibIOUV n = evalUVectorMemo (fibm n) n+fibIOUV n = evalUVectorMemo (fibm n) (n+1)  fibSTV :: Int -> Word-fibSTV n = runST $ evalVectorMemo (fibm n) n+fibSTV n = runST $ evalVectorMemo (fibm n) (n+1)  fibSTUV :: Int -> Word-fibSTUV n = runST $ evalUVectorMemo (fibm n) n+fibSTUV n = runST $ evalUVectorMemo (fibm n) (n+1)   fibIOVU :: Int -> IO Word-fibIOVU n = unsafeEvalVectorMemo (fibm n) n+fibIOVU n = unsafeEvalVectorMemo (fibm n) (n+1)  fibIOUVU :: Int -> IO Word-fibIOUVU n = unsafeEvalUVectorMemo (fibm n) n+fibIOUVU n = unsafeEvalUVectorMemo (fibm n) (n+1)  fibSTVU :: Int -> Word-fibSTVU n = runST $ unsafeEvalVectorMemo (fibm n) n+fibSTVU n = runST $ unsafeEvalVectorMemo (fibm n) (n+1)  fibSTUVU :: Int -> Word-fibSTUVU n = runST $ unsafeEvalUVectorMemo (fibm n) n+fibSTUVU n = runST $ unsafeEvalUVectorMemo (fibm n) (n+1)   fibIOVE :: Int -> IO Word@@ -87,7 +89,8 @@ -----------------------  {-# INLINE knap #-}-knap ws vs w = m (l-1) w+knap :: MonadMemo (Int, Int) Int m => [Int] -> [Int] -> Int -> m Int+knap ws vs = m (l-1)     where       l = length ws       wa = listArray (0,l-1) ws@@ -165,9 +168,7 @@         l2 <- mlcs ia (ib-1)         return (l1 `max` l2)       mlcs ai bi =-          memo (\abi -> -                    let (!ai,!bi) = abi `quotRem` lb-                    in lcs ai bi) (ai*lb + bi)+          memo (\abi -> uncurry lcs $! abi `quotRem` lb) (ai*lb + bi)  lcsIM :: [Int] -> [Int] -> Int lcsIM as bs = evalMemoState (lcsm as bs) IM.empty@@ -179,68 +180,118 @@ lcsSTUVE as bs = runST $ startEvalUVectorMemo (lcsm as bs)  +-- | Hofstadter Female and Male sequences+-- Mutually recursive memoized functions +gof :: (MonadTrans t, MonadCache Int Int m, MonadCache Int Int (t m)) => Int -> t m Int+gof 0 = return 1+gof i = do+  fs <- memol0 gof (i-1)+  ms <- memol1 gom fs+  return (i - ms)++gom :: (MonadTrans t, MonadCache Int Int m, MonadCache Int Int (t m)) => Int -> t m Int+gom 0 = return 0+gom i = do+  ms <- memol1 gom (i-1)+  fs <- memol0 gof ms+  return (i - fs)++fM :: Int -> Int+fM = startEvalMemo . startEvalMemoT . gof++fSTA :: Int -> Int+fSTA n = runST $ (`evalArrayMemo`(0,n)) . (`evalArrayMemo`(0,n)) . gof $ n++fSTAU :: Int -> Int+fSTAU n = runST $ (`evalUArrayMemo`(0,n)) . (`evalUArrayMemo`(0,n)) . gof $ n++fSTV :: Int -> Int+fSTV n = runST $ (`evalVectorMemo`(n+1)) . (`evalVectorMemo`(n+1)) . gof $ n++fSTVU :: Int -> Int+fSTVU n = runST $ (`evalUVectorMemo`(n+1)) . (`evalUVectorMemo`(n+1)) . gof $ n++fSTVUU :: Int -> Int+fSTVUU n = runST $ (`unsafeEvalUVectorMemo`(n+1)) . (`unsafeEvalUVectorMemo`(n+1)) . gof $ n+++main :: IO () main = defaultMainWith defaultConfig [-         bgroup "fib" [-           bgroup "pure" [-             bench "Map" $ whnf fibM n-           , bench "IntMap" $ whnf fibIM n-           ]-         , bgroup "ST" [-             bench "Array" $ whnf fibSTA n-           , bench "UArray" $ whnf fibSTUA n-           , bench "Vector" $ whnf fibSTV n-           , bench "UVector" $ whnf fibSTUV n-           , bench "Vector unsafe" $ whnf fibSTVU n-           , bench "UVector unsafe" $ whnf fibSTUVU n-           , bench "Vector exp" $ whnf fibSTVE n-           , bench "UVector exp" $ whnf fibSTUVE n-           ]-         , bgroup "IO" [-             bench "Array" $ whnfIO (fibIOA n)-           , bench "UArray" $ whnfIO (fibIOUA n)-           , bench "Vector" $ whnfIO (fibIOV n)-           , bench "UVector" $ whnfIO (fibIOUV n)-           , bench "Vector unsafe" $ whnfIO (fibIOVU n)-           , bench "UVector unsafe" $ whnfIO (fibIOUVU n)-           , bench "Vector exp" $ whnfIO (fibIOVE n)-           , bench "UVector exp" $ whnfIO (fibIOUVE n)-           ]-         ]-       , bgroup "knapsack" [-          bgroup "pure" [-             bench "Map" $ whnf (knapM ws vs) w-          ]-        , bgroup "ST" [-             bench "Array" $ whnf (knapSTA ws vs) w-           , bench "UArray" $ whnf (knapSTUA ws vs) w-          ]-        , bgroup "IO" [-             bench "Array" $ whnfIO (knapIOA ws vs w)-           , bench "UArray" $ whnfIO (knapIOUA ws vs w)-          ]-         ]-       , bgroup "LCS" [-          bgroup "pure" [-             bench "Map" $ whnf (lcsM as) bs-           , bench "IntMap" $ whnf (lcsIM as) bs-          ]-        , bgroup "ST" [-             bench "Array" $ whnf (lcsSTA as) bs-           , bench "UArray" $ whnf (lcsSTUA as) bs-           , bench "UVector exp" $ whnf (lcsSTUVE as) bs-           , bench "UVector" $ whnf (lcsSTUV as) bs-         ]-        ]-       ]-    where-      -- fib arg-      n = 100000-      -- knapsac args-      ws = [1..200]-      vs = [1..200]-      w = 800-      -- LCS args-      as = [1..400]-      bs = [100,102..800]+    bgroup "fib" [+      bgroup "pure" [+        bench "Map" $ whnf fibM n+      , bench "IntMap" $ whnf fibIM n+      ]+    , bgroup "ST" [+        bench "Array" $ whnf fibSTA n+      , bench "UArray" $ whnf fibSTUA n+      , bench "Vector" $ whnf fibSTV n+      , bench "UVector" $ whnf fibSTUV n+      , bench "Vector unsafe" $ whnf fibSTVU n+      , bench "UVector unsafe" $ whnf fibSTUVU n+      , bench "Vector exp" $ whnf fibSTVE n+      , bench "UVector exp" $ whnf fibSTUVE n+      ]+    , bgroup "IO" [+        bench "Array" $ whnfIO (fibIOA n)+      , bench "UArray" $ whnfIO (fibIOUA n)+      , bench "Vector" $ whnfIO (fibIOV n)+      , bench "UVector" $ whnfIO (fibIOUV n)+      , bench "Vector unsafe" $ whnfIO (fibIOVU n)+      , bench "UVector unsafe" $ whnfIO (fibIOUVU n)+      , bench "Vector exp" $ whnfIO (fibIOVE n)+      , bench "UVector exp" $ whnfIO (fibIOUVE n)+      ]+    ]+  , bgroup "knapsack" [+      bgroup "pure" [+          bench "Map" $ whnf (knapM ws vs) w+      ]+    , bgroup "ST" [+          bench "Array" $ whnf (knapSTA ws vs) w+        , bench "UArray" $ whnf (knapSTUA ws vs) w+      ]+    , bgroup "IO" [+          bench "Array" $ whnfIO (knapIOA ws vs w)+        , bench "UArray" $ whnfIO (knapIOUA ws vs w)+      ]+    ]+  , bgroup "LCS" [+      bgroup "pure" [+          bench "Map" $ whnf (lcsM as) bs+        , bench "IntMap" $ whnf (lcsIM as) bs+      ]+    , bgroup "ST" [+          bench "Array" $ whnf (lcsSTA as) bs+        , bench "UArray" $ whnf (lcsSTUA as) bs+        , bench "UVector exp" $ whnf (lcsSTUVE as) bs+        , bench "UVector" $ whnf (lcsSTUV as) bs+      ]+    ]+  , bgroup "Hofstadter" [+      bgroup "pure" [+          bench "Map" $ whnf fM fn+      ]+    , bgroup "ST" [+          bench "Array" $ whnf fSTA fn+        , bench "UArray" $ whnf fSTAU fn+        , bench "Vector" $ whnf fSTV fn+        , bench "UVector" $ whnf fSTVU fn+        , bench "UVector unsafe" $ whnf fSTVUU fn+      ]+    ]+  ]+  where+    -- fib arg+    n = 100000+    -- knapsac args+    ws = [1..200]+    vs = [1..200]+    w = 800+    -- LCS args+    as = [1..400]+    bs = [100,102..800]+    -- Hofstadter+    fn = 100000            
example/Basic.hs view
@@ -287,7 +287,7 @@  evalFibmwSTA n = runST $ evalArrayMemo (runWriterT (fibmw n)) (0,n) -evalFibmwSTV n = runST $ evalVectorMemo (runWriterT (fibmw n)) n+evalFibmwSTV n = runST $ evalVectorMemo (runWriterT (fibmw n)) (n+1)  runFibmwST :: Integer -> ((Integer,String), Array Integer (Maybe (Integer,String))) runFibmwST n = runST $ do
monad-memo.cabal view
@@ -1,6 +1,6 @@ Name:               monad-memo -Version:            0.5.0+Version:            0.5.1  -- A short (one-line) description of the package. Synopsis:           Memoization monad transformer@@ -52,7 +52,11 @@ -- Constraint on the version of Cabal needed to build this package. Cabal-version:      >=1.10 -Tested-with:        GHC==7.10.3, GHC==8.2.2, GHC==8.4.3+Tested-with:+  GHC==7.8.4,+  GHC==7.10.3,+  GHC==8.2.2,+  GHC==8.4.3  Extra-source-files:   CHANGES,@@ -80,6 +84,9 @@           array >= 0.3,           vector >= 0.7,           primitive >= 0.3+  if impl(ghc < 7.10)+    build-depends:+          transformers-compat >= 0.3   exposed-modules:           Control.Monad.Memo,           Control.Monad.Memo.Class,@@ -114,6 +121,9 @@           QuickCheck >= 2.0,           test-framework-quickcheck2 >= 0.2.9,           test-framework >= 0.3.3+  if impl(ghc < 7.10)+    build-depends:+          transformers-compat >= 0.3   other-modules:           Control.Monad.Memo,           Control.Monad.Memo.Class,@@ -146,6 +156,9 @@           vector >= 0.7,           primitive >= 0.3,           criterion >= 0.6+  if impl(ghc < 7.10)+    build-depends:+          transformers-compat >= 0.3   other-modules:           Control.Monad.Memo,           Control.Monad.Memo.Class,
test/MemoTest.hs view
@@ -1,3 +1,4 @@+{-# OPTIONS_GHC -fno-warn-missing-signatures #-} {-# LANGUAGE FlexibleInstances, FlexibleContexts #-}  module MemoTest@@ -15,7 +16,7 @@ import Test.QuickCheck import Test.QuickCheck.Monadic import System.Random-import Test.Framework (defaultMain, testGroup)+import Test.Framework (testGroup) import Test.Framework.Providers.QuickCheck2 (testProperty)  import Control.Monad.Memo@@ -84,9 +85,9 @@ runFibmr r = startEvalMemo . (`runReaderT`r) . fibmr  -prop_ReaderEqv :: SmallInt Int -> SmallInt Int -> Bool+prop_ReaderEqv :: SmallInt Int -> SmallInt Int -> Property prop_ReaderEqv (SmallInt r) (SmallInt n) =-    ((`runReader` r) . fibr  $ n) == (startEvalMemo . (`runReaderT` r) . fibmr $ n)+    runFibr r n === runFibmr r n  prop_ReaderSTEqv :: SmallInt Integer -> SmallInt Integer -> Bool prop_ReaderSTEqv (SmallInt r) (SmallInt n) =@@ -152,7 +153,7 @@   s <- get   f1 <- fibs (n-1)   f2 <- fibs (n-2)-  modify $ \s -> s+1+  modify (+1)   return (f1+f2+s)  fibms 0 = return 0@@ -161,7 +162,7 @@   s <- get   f1 <- memo fibms (n-1)   f2 <- memo fibms (n-2)-  modify $ \s -> s+1+  modify (+1)   return (f1+f2+s)  prop_StateEqv :: SmallInt Int -> SmallInt Int -> Bool@@ -210,6 +211,7 @@         x = toInt sx         y = toInt sy + -- Same as above but without explicit uncurring fm2 :: Int -> MemoFG (Int,String) fm2 0 = return (1,"+")@@ -226,8 +228,8 @@   return $ fst fn - g  evalAll2 = startEvalMemo . startEvalMemoT-evalFm2 = evalAll . fm2-evalGm2 n m = evalAll $ gm2 n m+evalFm2 = evalAll2 . fm2+evalGm2 n m = evalAll2 $ gm2 n m   prop_Mutual2FEqv :: SmallInt Int -> Bool@@ -255,9 +257,6 @@ fibSTUA :: Int -> Int fibSTUA n = runST $ evalUArrayMemo (fibm n) (0,n) -fibSTUAD :: Int -> Double-fibSTUAD n = runST $ evalUArrayMemo (fibm n) (0,n)- fibIOA :: Integer -> IO Integer fibIOA n = evalArrayMemo (fibm n) (0,n) @@ -292,19 +291,19 @@ -----------------  fibSTV :: Int -> Integer-fibSTV n = runST $ evalVectorMemo (fibm n) n+fibSTV n = runST $ evalVectorMemo (fibm n) (n+1)  prop_STVEqv :: MedInt Int -> Bool prop_STVEqv (MedInt n) = fibMap n == fibSTV n  fibSTUV :: Int -> Int-fibSTUV n = runST $ evalUVectorMemo (fibm n) n+fibSTUV n = runST $ evalUVectorMemo (fibm n) (n+1)  prop_STUVEqv :: MedInt Int -> Bool prop_STUVEqv (MedInt n) = fibMap n == fibSTUV n  fibIOV :: Int -> IO Integer-fibIOV n = evalVectorMemo (fibm n) n+fibIOV n = evalVectorMemo (fibm n) (n+1)  prop_IOVEqv :: MedInt Int -> Property prop_IOVEqv (MedInt n) = monadicIO $ do@@ -312,7 +311,7 @@                            assert $ r == fibMap n  fibIOUV :: Int -> IO Int-fibIOUV n = evalUVectorMemo (fibm n) n+fibIOUV n = evalUVectorMemo (fibm n) (n+1)  prop_IOUVEqv :: MedInt Int -> Property prop_IOUVEqv (MedInt n) = monadicIO $ do@@ -355,19 +354,19 @@ ------------------------  fibSTUSV :: Int -> Integer-fibSTUSV n = runST $ UV.unsafeEvalVectorMemo (fibm n) n+fibSTUSV n = runST $ UV.unsafeEvalVectorMemo (fibm n) (n+1)  prop_STUSVEqv :: MedInt Int -> Bool prop_STUSVEqv (MedInt n) = fibMap n == fibSTUSV n  fibSTUSUV :: Int -> Int-fibSTUSUV n = runST $ UV.unsafeEvalUVectorMemo (fibm n) n+fibSTUSUV n = runST $ UV.unsafeEvalUVectorMemo (fibm n) (n+1)  prop_STUSUVEqv :: MedInt Int -> Bool prop_STUSUVEqv (MedInt n) = fibMap n == fibSTUSUV n  fibIOUSV :: Int -> IO Integer-fibIOUSV n = UV.unsafeEvalVectorMemo (fibm n) n+fibIOUSV n = UV.unsafeEvalVectorMemo (fibm n) (n+1)  prop_IOUSVEqv :: MedInt Int -> Property prop_IOUSVEqv (MedInt n) = monadicIO $ do@@ -375,7 +374,7 @@                            assert $ r == fibMap n  fibIOUSUV :: Int -> IO Int-fibIOUSUV n = UV.unsafeEvalUVectorMemo (fibm n) n+fibIOUSUV n = UV.unsafeEvalUVectorMemo (fibm n) (n+1)  prop_IOUSUVEqv :: MedInt Int -> Property prop_IOUSUVEqv (MedInt n) = monadicIO $ do@@ -383,39 +382,163 @@                            assert $ r == fibMap n  +-- | Hofstadter Female and Male sequences+-- Mutually recursive functions++hf :: Int -> Int+hf n =+  gof n+  where+    gof 0 = 1+    gof i = i - ms !! (fs !! (i-1))+    gom 0 = 0+    gom i = i - fs !! (ms !! (i-1))+    fs = [gof j | j <- [0..n]]+    ms = [gom j | j <- [0..n]]++-- hfm :: a -> t1 m a+hfm n = gof n+  where+    gof 0 = return 1+    gof i = do+      fs <- memol0 gof (i-1)+      ms <- memol1 gom fs+      return (i - ms)+    gom 0 = return 0+    gom i = do+      ms <- memol1 gom (i-1)+      fs <- memol0 gof ms+      return (i - fs)++hfM :: Int -> Int+hfM = startEvalMemo . startEvalMemoT . hfm++prop_hfMEqv :: MedInt Int -> Property+prop_hfMEqv (MedInt n) =+  hfM n === hf n+++hfIOA :: Int -> IO Int+hfIOA n = (`evalArrayMemo`(0,n)) . (`evalArrayMemo`(0,n)) . hfm $ n++hfIOAU :: Int -> IO Int+hfIOAU n = (`evalUArrayMemo`(0,n)) . (`evalUArrayMemo`(0,n)) . hfm $ n++hfSTA :: Int -> Int+hfSTA n = runST $ (`evalArrayMemo`(0,n)) . (`evalArrayMemo`(0,n)) . hfm $ n++hfSTAU :: Int -> Int+hfSTAU n = runST $ (`evalUArrayMemo`(0,n)) . (`evalUArrayMemo`(0,n)) . hfm $ n++hfIOV :: Int -> IO Int+hfIOV n = (`evalVectorMemo`(n+1)) . (`evalVectorMemo`(n+1)) . hfm $ n++hfIOVU :: Int -> IO Int+hfIOVU n = (`evalUVectorMemo`(n+1)) . (`evalUVectorMemo`(n+1)) . hfm $ n++hfSTV :: Int -> Int+hfSTV n = runST $ (`evalVectorMemo`(n+1)) . (`evalVectorMemo`(n+1)) . hfm $ n++hfSTVU :: Int -> Int+hfSTVU n = runST $ (`evalUVectorMemo`(n+1)) . (`evalUVectorMemo`(n+1)) . hfm $ n++hfSTVE :: Int -> Int+hfSTVE n = runST $ (EV.startEvalVectorMemo) . (EV.startEvalVectorMemo) . hfm $ n++hfSTVUE :: Int -> Int+hfSTVUE n = runST $ (EV.startEvalUVectorMemo) . (EV.startEvalUVectorMemo) . hfm $ n++prop_hfIOEqv :: MedInt Int -> Property+prop_hfIOEqv (MedInt n) = monadicIO $ do+  hfIOAn <- run $ hfIOA n+  hfIOAUn <- run $ hfIOAU n+  hfIOVn <- run $ hfIOV n+  hfIOVUn <- run $ hfIOVU n+  return $+    hfIOAn === hfn .&&.+    hfIOAUn === hfn .&&.+    hfIOVn === hfn .&&.+    hfIOVUn === hfn+  where+    hfn = hf n++prop_hfSTAEqv :: MedInt Int -> Property+prop_hfSTAEqv (MedInt n) =+  hfSTA n === hf n++prop_hfSTAUEqv :: MedInt Int -> Property+prop_hfSTAUEqv (MedInt n) =+  hfSTAU n === hf n++prop_hfSTVEqv :: MedInt Int -> Property+prop_hfSTVEqv (MedInt n) =+  hfSTV n === hf n++prop_hfSTVUEqv :: MedInt Int -> Property+prop_hfSTVUEqv (MedInt n) =+  hfSTVU n === hf n++prop_hfSTVEEqv :: MedInt Int -> Property+prop_hfSTVEEqv (MedInt n) =+  hfSTVE n === hf n++prop_hfSTVUEEqv :: MedInt Int -> Property+prop_hfSTVUEEqv (MedInt n) =+  hfSTVUE n === hf n+ tests = [-        testGroup "Transformers" [-                       testProperty "ReaderEqv"         prop_ReaderEqv,-                       testProperty "ReaderSTEqv"       prop_ReaderSTEqv,-                       testProperty "WriterEqv"         prop_WriterEqv,-                       testProperty "ContEqv"           prop_ContEqv,-                       testProperty "ContSTUEqv"        prop_ContSTUEqv,-                       testProperty "StateEqv"          prop_StateEqv-                      ],-        testGroup "Others" [-                       testProperty "MutualFGEqv"       prop_MutualFEqv,-                       testProperty "MutualCurryFGEqv"  prop_Mutual2FEqv-                       ],-        testGroup "Different memo-caches" [-                       testGroup "ArrayCache" [-                                      testProperty "Data.IntMap cache" prop_IntMapEqv,-                                      testProperty "STArray cache"     prop_STAEqv,-                                      testProperty "STUArray cache"    prop_STUAEqv,-                                      testProperty "STUArray Double"   prop_STUADEqv,-                                      testProperty "IOArray cache"     prop_IOAEqv,-                                      testProperty "IOUArray cache"    prop_IOUAEqv-                                     ],-                       testGroup "VectorCache" [-                                      testProperty "STVector cache"    prop_STVEqv,-                                      testProperty "STUVector cache"   prop_STUVEqv,-                                      testProperty "IOVector cache"    prop_IOVEqv,-                                      testProperty "IOUVector cache"   prop_IOUVEqv-                                     ],-                       testGroup "Expandable VectorCache" [-                                      testProperty "Exp STVector cache"    prop_STEVEqv,-                                      testProperty "Exp STUVector cache"   prop_STEUVEqv,-                                      testProperty "Exp IOVector cache"    prop_IOEVEqv,-                                      testProperty "Exp IOUVector cache"   prop_IOEUVEqv-                                     ]-                      ]+    testGroup "Transformers" [+      testProperty "ReaderEqv"         prop_ReaderEqv,+      testProperty "ReaderSTEqv"       prop_ReaderSTEqv,+      testProperty "WriterEqv"         prop_WriterEqv,+      testProperty "ContEqv"           prop_ContEqv,+      testProperty "ContSTUEqv"        prop_ContSTUEqv,+      testProperty "StateEqv"          prop_StateEqv+    ],+    testGroup "Others" [+      testProperty "MutualFEqv"        prop_MutualFEqv,+      testProperty "MutualGEqv"        prop_MutualGEqv,+      testProperty "MutualCurryFEqv"   prop_Mutual2FEqv,+      testProperty "MutualCurryGEqv"   prop_Mutual2GEqv,+      testGroup "Hofstadter" [+        testProperty "Map"             prop_hfMEqv,+        testProperty "IO (Arr & Vec)"  prop_hfIOEqv,+        testGroup "ST" [+          testProperty "Vector"      prop_hfSTVEqv,+          testProperty "UVector"     prop_hfSTVUEqv,+          testProperty "Array"       prop_hfSTAEqv,+          testProperty "UArray"      prop_hfSTAUEqv,+          testProperty "Vector exp"  prop_hfSTVEEqv,+          testProperty "UVector exp" prop_hfSTVUEEqv+        ]+      ]+    ],+    testGroup "Different memo-caches" [+      testGroup "ArrayCache" [+        testProperty "Data.IntMap cache" prop_IntMapEqv,+        testProperty "STArray cache"     prop_STAEqv,+        testProperty "STUArray cache"    prop_STUAEqv,+        testProperty "STUArray Double"   prop_STUADEqv,+        testProperty "IOArray cache"     prop_IOAEqv,+        testProperty "IOUArray cache"    prop_IOUAEqv+      ],+      testGroup "VectorCache" [+        testProperty "STVector cache"    prop_STVEqv,+        testProperty "STUVector cache"   prop_STUVEqv,+        testProperty "IOVector cache"    prop_IOVEqv,+        testProperty "IOUVector cache"   prop_IOUVEqv+      ],+      testGroup "Expandable VectorCache" [+        testProperty "STVector cache"    prop_STEVEqv,+        testProperty "STUVector cache"   prop_STEUVEqv,+        testProperty "IOVector cache"    prop_IOEVEqv,+        testProperty "IOUVector cache"   prop_IOEUVEqv+      ],+      testGroup "Unsafe VectorCache" [+        testProperty "STVector cache"    prop_STUSVEqv,+        testProperty "STUVector cache"   prop_STUSUVEqv,+        testProperty "IOVector cache"    prop_IOUSVEqv,+        testProperty "IOUVector cache"   prop_IOUSUVEqv+      ]     ]+  ]