@@ -0,0 +1,65 @@
1+module Data.Vault
2+ ( Vault
3+ , Key
4+ , empty
5+ , newKey
6+ , insert
7+ , lookup
8+ , delete
9+ ) where
10+
11+import Prelude
12+
13+import Control.Monad.Eff (Eff)
14+import Control.Monad.Eff.Unsafe (unsafeCoerceEff)
15+import Control.Monad.Eff.Ref (REF, Ref, newRef, writeRef, modifyRef')
16+
17+import Data.Map as M
18+import Data.Maybe (Maybe(..))
19+import Data.Newtype (class Newtype, over)
20+import Data.Vault.Internal (Unique, newUnique)
21+
22+newtype Vault = Vault (M.Map Unique Item)
23+
24+data Key a = Key Unique (Item' a)
25+
26+type Item = Eff (ref :: REF) Unit
27+
28+type Item' a = Ref (Maybe a)
29+
30+-- | The empty vault
31+empty :: Vault
32+empty = Vault M.empty
33+
34+newKey :: forall eff a. Eff (ref :: REF | eff) (Key a)
35+newKey = do
36+ k <- newUnique
37+ ref <- newRef Nothing
38+ pure $ Key k ref
39+
40+insert :: forall a. Key a -> a -> Vault -> Vault
41+insert (Key k ref) a = over Vault $ M.insert k (writeRef ref (Just a))
42+
43+delete :: forall a. Key a -> Vault -> Vault
44+delete (Key k _) = over Vault $ M.delete k
45+
46+lookup :: forall eff a. Key a -> Vault -> Eff (ref :: REF | eff) (Maybe a)
47+lookup (Key k ref) (Vault m) = case M.lookup k m of
48+ Nothing -> pure Nothing
49+ Just act -> do
50+ _ <- coerceVaultItem act
51+ modifyRef' ref rollItem
52+
53+coerceVaultItem :: forall eff a. Eff (ref :: REF) a -> Eff (ref :: REF | eff) a
54+coerceVaultItem = unsafeCoerceEff
55+
56+rollItem :: forall a. Maybe a -> { state :: Maybe a, value :: Maybe a }
57+rollItem a = { state: Nothing, value: a }
58+
59+derive instance newtypeVault :: Newtype Vault _
60+
61+instance eqKey :: Eq (Key a) where
62+ eq (Key a _) (Key b _) = a == b
63+
64+instance ordKey :: Ord (Key a) where
65+ compare (Key a _) (Key b _) = compare a b