2
2
{-# LANGUAGE DefaultSignatures #-}
3
3
{-# LANGUAGE DerivingStrategies #-}
4
4
{-# LANGUAGE FlexibleContexts #-}
5
+ {-# LANGUAGE FlexibleInstances #-}
5
6
{-# LANGUAGE GADTs #-}
6
7
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
7
8
{-# LANGUAGE MultiParamTypeClasses #-}
@@ -31,6 +32,8 @@ module Control.Monad.Class.MonadSTM
31
32
, TQueueDefault (.. )
32
33
-- * Default 'TBQueue' implementation
33
34
, TBQueueDefault (.. )
35
+ -- * Default 'TArray' implementation
36
+ , TArrayDefault (.. )
34
37
-- * MonadThrow aliases
35
38
, throwSTM
36
39
, catchSTM
@@ -46,6 +49,7 @@ module Control.Monad.Class.MonadSTM
46
49
47
50
import Prelude hiding (read )
48
51
52
+ import qualified Control.Concurrent.STM.TArray as STM
49
53
import qualified Control.Concurrent.STM.TBQueue as STM
50
54
import qualified Control.Concurrent.STM.TMVar as STM
51
55
import qualified Control.Concurrent.STM.TQueue as STM
@@ -65,7 +69,13 @@ import qualified Control.Monad.Class.MonadThrow as MonadThrow
65
69
66
70
import Control.Applicative (Alternative (.. ))
67
71
import Control.Exception
72
+ import Data.Array (Array , bounds )
73
+ import qualified Data.Array as Array
74
+ import Data.Array.Base (IArray (numElements ), MArray (.. ),
75
+ arrEleBottom , listArray , unsafeAt )
76
+ import Data.Foldable (traverse_ )
68
77
import Data.Function (on )
78
+ import Data.Ix (Ix , rangeSize )
69
79
import Data.Kind (Type )
70
80
import Data.Typeable (Typeable )
71
81
import GHC.Stack
@@ -148,6 +158,8 @@ class ( Monad m
148
158
isFullTBQueue :: TBQueue m a -> STM m Bool
149
159
unGetTBQueue :: TBQueue m a -> a -> STM m ()
150
160
161
+ type TArray m :: Type -> Type -> Type
162
+
151
163
-- Helpful derived functions with default implementations
152
164
153
165
newTVarIO :: a -> m (TVar m a )
@@ -314,15 +326,19 @@ newEmptyTMVarM = newEmptyTMVarIO
314
326
--
315
327
class MonadSTM m
316
328
=> MonadLabelledSTM m where
317
- labelTVar :: TVar m a -> String -> STM m ()
318
- labelTMVar :: TMVar m a -> String -> STM m ()
319
- labelTQueue :: TQueue m a -> String -> STM m ()
320
- labelTBQueue :: TBQueue m a -> String -> STM m ()
321
-
322
- labelTVarIO :: TVar m a -> String -> m ()
323
- labelTMVarIO :: TMVar m a -> String -> m ()
324
- labelTQueueIO :: TQueue m a -> String -> m ()
325
- labelTBQueueIO :: TBQueue m a -> String -> m ()
329
+ labelTVar :: TVar m a -> String -> STM m ()
330
+ labelTMVar :: TMVar m a -> String -> STM m ()
331
+ labelTQueue :: TQueue m a -> String -> STM m ()
332
+ labelTBQueue :: TBQueue m a -> String -> STM m ()
333
+ labelTArray :: (Ix i , Show i )
334
+ => TArray m i e -> String -> STM m ()
335
+
336
+ labelTVarIO :: TVar m a -> String -> m ()
337
+ labelTMVarIO :: TMVar m a -> String -> m ()
338
+ labelTQueueIO :: TQueue m a -> String -> m ()
339
+ labelTBQueueIO :: TBQueue m a -> String -> m ()
340
+ labelTArrayIO :: (Ix i , Show i )
341
+ => TArray m i e -> String -> m ()
326
342
327
343
--
328
344
-- default implementations
@@ -340,6 +356,13 @@ class MonadSTM m
340
356
=> TBQueue m a -> String -> STM m ()
341
357
labelTBQueue = labelTBQueueDefault
342
358
359
+ default labelTArray :: ( TArray m ~ TArrayDefault m
360
+ , Ix i
361
+ , Show i
362
+ )
363
+ => TArray m i e -> String -> STM m ()
364
+ labelTArray = labelTArrayDefault
365
+
343
366
default labelTVarIO :: TVar m a -> String -> m ()
344
367
labelTVarIO = \ v l -> atomically (labelTVar v l)
345
368
@@ -352,6 +375,10 @@ class MonadSTM m
352
375
default labelTBQueueIO :: TBQueue m a -> String -> m ()
353
376
labelTBQueueIO = \ v l -> atomically (labelTBQueue v l)
354
377
378
+ default labelTArrayIO :: (Ix i , Show i )
379
+ => TArray m i e -> String -> m ()
380
+ labelTArrayIO = \ v l -> atomically (labelTArray v l)
381
+
355
382
356
383
-- | This type class is indented for 'io-sim', where one might want to access
357
384
-- 'TVar' in the underlying 'ST' monad.
@@ -511,6 +538,7 @@ instance MonadSTM IO where
511
538
type TMVar IO = STM. TMVar
512
539
type TQueue IO = STM. TQueue
513
540
type TBQueue IO = STM. TBQueue
541
+ type TArray IO = STM. TArray
514
542
515
543
newTVar = STM. newTVar
516
544
readTVar = STM. readTVar
@@ -566,11 +594,13 @@ instance MonadLabelledSTM IO where
566
594
labelTMVar = \ _ _ -> return ()
567
595
labelTQueue = \ _ _ -> return ()
568
596
labelTBQueue = \ _ _ -> return ()
597
+ labelTArray = \ _ _ -> return ()
569
598
570
599
labelTVarIO = \ _ _ -> return ()
571
600
labelTMVarIO = \ _ _ -> return ()
572
601
labelTQueueIO = \ _ _ -> return ()
573
602
labelTBQueueIO = \ _ _ -> return ()
603
+ labelTArrayIO = \ _ _ -> return ()
574
604
575
605
-- | noop instance
576
606
--
@@ -910,6 +940,47 @@ unGetTBQueueDefault (TBQueue rsize read wsize _write _size) a = do
910
940
writeTVar read (a: xs)
911
941
912
942
943
+ --
944
+ -- Default `TArray` implementation
945
+ --
946
+
947
+ -- | Default implementation of 'TArray'.
948
+ --
949
+ data TArrayDefault m i e = TArray (Array i (TVar m e ))
950
+ deriving Typeable
951
+
952
+ deriving instance (Eq (TVar m e ), Ix i ) => Eq (TArrayDefault m i e )
953
+
954
+ instance (Monad stm , MonadSTM m , stm ~ STM m )
955
+ => MArray (TArrayDefault m ) e stm where
956
+ getBounds (TArray a) = return (bounds a)
957
+ newArray b e = do
958
+ a <- rep (rangeSize b) (newTVar e)
959
+ return $ TArray (listArray b a)
960
+ newArray_ b = do
961
+ a <- rep (rangeSize b) (newTVar arrEleBottom)
962
+ return $ TArray (listArray b a)
963
+ unsafeRead (TArray a) i = readTVar $ unsafeAt a i
964
+ unsafeWrite (TArray a) i e = writeTVar (unsafeAt a i) e
965
+ getNumElements (TArray a) = return (numElements a)
966
+
967
+ rep :: Monad m => Int -> m a -> m [a ]
968
+ rep n m = go n []
969
+ where
970
+ go 0 xs = return xs
971
+ go i xs = do
972
+ x <- m
973
+ go (i- 1 ) (x: xs)
974
+
975
+ labelTArrayDefault :: ( MonadLabelledSTM m
976
+ , Ix i
977
+ , Show i
978
+ )
979
+ => TArrayDefault m i e -> String -> STM m ()
980
+ labelTArrayDefault (TArray arr) name = do
981
+ let as = Array. assocs arr
982
+ traverse_ (\ (i, v) -> labelTVar v (name ++ " :" ++ show i)) as
983
+
913
984
-- | 'throwIO' specialised to @stm@ monad.
914
985
--
915
986
throwSTM :: (MonadSTM m , MonadThrow. MonadThrow (STM m ), Exception e )
@@ -1021,6 +1092,8 @@ instance MonadSTM m => MonadSTM (ContT r m) where
1021
1092
isFullTBQueue = WrappedSTM . isFullTBQueue
1022
1093
unGetTBQueue = WrappedSTM .: unGetTBQueue
1023
1094
1095
+ type TArray (ContT r m ) = TArray m
1096
+
1024
1097
1025
1098
instance MonadSTM m => MonadSTM (ReaderT r m ) where
1026
1099
type STM (ReaderT r m ) = WrappedSTM Reader r m
@@ -1074,6 +1147,8 @@ instance MonadSTM m => MonadSTM (ReaderT r m) where
1074
1147
isFullTBQueue = WrappedSTM . isFullTBQueue
1075
1148
unGetTBQueue = WrappedSTM .: unGetTBQueue
1076
1149
1150
+ type TArray (ReaderT r m ) = TArray m
1151
+
1077
1152
1078
1153
instance (Monoid w , MonadSTM m ) => MonadSTM (WriterT w m ) where
1079
1154
type STM (WriterT w m ) = WrappedSTM Writer w m
@@ -1127,6 +1202,8 @@ instance (Monoid w, MonadSTM m) => MonadSTM (WriterT w m) where
1127
1202
isFullTBQueue = WrappedSTM . isFullTBQueue
1128
1203
unGetTBQueue = WrappedSTM .: unGetTBQueue
1129
1204
1205
+ type TArray (WriterT w m ) = TArray m
1206
+
1130
1207
1131
1208
instance MonadSTM m => MonadSTM (StateT s m ) where
1132
1209
type STM (StateT s m ) = WrappedSTM State s m
@@ -1180,6 +1257,8 @@ instance MonadSTM m => MonadSTM (StateT s m) where
1180
1257
isFullTBQueue = WrappedSTM . isFullTBQueue
1181
1258
unGetTBQueue = WrappedSTM .: unGetTBQueue
1182
1259
1260
+ type TArray (StateT s m ) = TArray m
1261
+
1183
1262
1184
1263
instance MonadSTM m => MonadSTM (ExceptT e m ) where
1185
1264
type STM (ExceptT e m ) = WrappedSTM Except e m
@@ -1233,6 +1312,8 @@ instance MonadSTM m => MonadSTM (ExceptT e m) where
1233
1312
isFullTBQueue = WrappedSTM . isFullTBQueue
1234
1313
unGetTBQueue = WrappedSTM .: unGetTBQueue
1235
1314
1315
+ type TArray (ExceptT e m ) = TArray m
1316
+
1236
1317
1237
1318
instance (Monoid w , MonadSTM m ) => MonadSTM (RWST r w s m ) where
1238
1319
type STM (RWST r w s m ) = WrappedSTM RWS (r , w , s ) m
@@ -1286,6 +1367,8 @@ instance (Monoid w, MonadSTM m) => MonadSTM (RWST r w s m) where
1286
1367
isFullTBQueue = WrappedSTM . isFullTBQueue
1287
1368
unGetTBQueue = WrappedSTM .: unGetTBQueue
1288
1369
1370
+ type TArray (RWST r w s m ) = TArray m
1371
+
1289
1372
1290
1373
(.:) :: (c -> d ) -> (a -> b -> c ) -> (a -> b -> d )
1291
1374
(f .: g) x y = f (g x y)
0 commit comments