ReaderT Design Pattern Reflection
:set +m
:set -package stm
:set -package transforms
:set -package lifted-async
:set -package mtl
{-# LANGUAGE FlexibleContexts #-}
import Control.Concurrent.Async.Lifted.Safe
import Control.Monad.Reader
import Control.Concurrent.STM
modify :: (MonadReader (TVar Int) m, MonadIO m)
=> (Int -> Int)
-> m ()
modify f = do
ref <- ask
liftIO $ atomically $ modifyTVar' ref f
ref <- newTVarIO 4
runReaderT (concurrently (modify (+ 1)) (modify (+ 2))) ref
readTVarIO ref >>= print
4
org mode の source block では 4
になってしまう。正しくは 7
。
cabal
ではうまくいく。
#!/usr/bin/env cabal
{- cabal:
build-depends: base, stm, lifted-async, transformers, mtl
-}
{-# LANGUAGE FlexibleContexts #-}
import Control.Concurrent.Async.Lifted.Safe
import Control.Monad.Reader
import Control.Concurrent.STM
modify :: (MonadReader (TVar Int) m, MonadIO m)
=> (Int -> Int)
-> m ()
modify f = do
ref <- ask
liftIO $ atomically $ modifyTVar' ref f
main :: IO ()
main = do
ref <- newTVarIO 4
runReaderT (concurrently (modify (+ 1)) (modify (+ 2))) ref
readTVarIO ref >>= print
7
応用として、 m()
ではなく、 m(Maybe Int)
とするとこんな風になる。
#!/usr/bin/env cabal
{- cabal:
build-depends: base, stm, lifted-async, transformers, mtl
-}
{-# LANGUAGE FlexibleContexts #-}
import Control.Concurrent.Async.Lifted.Safe
import Control.Monad.Reader
import Control.Concurrent.STM
modify :: (MonadReader (TVar Int) m, MonadIO m)
=> (Int -> Int)
-> m (Maybe Int)
modify f = do
ref <- ask
liftIO $ atomically $ do
modifyTVar' ref f
Just <$> readTVar ref
main :: IO ()
main = do
ref <- newTVarIO 4
res <- runReaderT (concurrently (modify (+ 1)) (modify (+ 2))) ref
readTVarIO ref >>= print
print res
(Just 5,Just 7)
concurrently
の type signature は
concurrently :: forall m a b. (MonadBaseControl IO m, Forall (Pure m)) => m a -> m b -> m (a, b)
なので、結果は tuple でよい。