File: Vector.hs

package info (click to toggle)
haskell-monad-memo 0.5.1-1
  • links: PTS
  • area: main
  • in suites: bullseye
  • size: 228 kB
  • sloc: haskell: 2,159; makefile: 6
file content (83 lines) | stat: -rw-r--r-- 2,578 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
{- |
Module      :  Sample.Memo
Copyright   :  (c) Eduard Sergeev 2013
License     :  BSD-style (see the file LICENSE)

Maintainer  :  eduard.sergeev@gmail.com
Stability   :  experimental
Portability :  non-portable

More advanced examples
-}

{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances,
  TypeFamilies, TypeSynonymInstances #-}

module Example.Customisation.Vector
(

  -- * Custom `VectorMemo`
  -- $UnboxedTupleVector
  BoolInt,
  evalFibSTUV,
  runFibSTUV,
  evalFibIOUV,
  runFibIOUV

) where

import Control.Monad
import Control.Monad.ST
import Control.Monad.Primitive
import qualified Data.Vector.Unboxed as UV
import qualified Data.Vector.Unboxed.Mutable as UM

import Data.MaybeLike
import Control.Monad.Memo.Class
import Control.Monad.Trans.Memo.ReaderCache
import Control.Monad.Memo.Vector


fibm 0 = return 0
fibm 1 = return 1
fibm n = liftM2 (+) (memo fibm (n-1)) (memo fibm (n-2))

{- $UnboxedTupleVector
New custom types, not handled by "Control.Monad.Trans.Memo.Vector.Instances", can be used inside `VectorCache` if necessary.
For example if we need a full range of `Int` (including `minBound` and `maxBound`) we can represent `Maybelike` `Int` as a pair @(Bool,Int)@ with `nothing` indicated by the @False@ value of its first element. `Data.Vector.Unboxed.Mutable.MVector` can store such pair efficiently (internally as a pair of unboxed arrays) so all we have to do then is to define `MaybeLike` and `VectorMemo` instances for our product-type.
-}

-- | Unboxed `Int` which can memoize entire range of `Int` values
-- by indicating `nothing` values by setting its first element to @False@
type BoolInt = (Bool,Int)

-- | MaybeLike instance for our unboxed Int
instance MaybeLike BoolInt Int where
    nothing = (False,0)
    isNothing (b,_) = not b
    just a = (True,a)
    fromJust (True,a) = a

-- | UVectorMemo instance will allow us to use all @eval*@ and @run*@ functions
-- from unboxed part of "Control.Monad.Trans.Memo.Vector" module 
instance UVectorMemo Int BoolInt


-- | Use standard function once we defined the instance for `VectorMemo`
evalFibSTUV :: Int -> Int
evalFibSTUV n = runST $ evalUVectorMemo (fibm n) (n+1)

runFibSTUV :: Int -> (Int, UV.Vector (Bool,Int))
runFibSTUV n = runST $ do 
   (a,vec) <- runUVectorMemo (fibm n) (n+1)
   ivec <- UV.unsafeFreeze vec
   return (a, ivec)

evalFibIOUV :: Int -> IO Int
evalFibIOUV n = evalUVectorMemo (fibm n) (n+1) 

runFibIOUV :: Int -> IO (Int, UV.Vector (Bool,Int))
runFibIOUV n = do
  (a, vec) <- runUVectorMemo (fibm n) (n+1) 
  ivec <- UV.unsafeFreeze vec
  return (a, ivec)