How to make Koen Claessen's concurrency monad with pure variables?

Turion

It's known how to make a pure concurrency monad based on ContT, based on a functional pearl of Koen Claessen:

data Action m where
  Atom :: m (Action m) -> Action m
  Fork :: [Action m] -> Action m
  Stop :: Action m

fork :: Applicative m => [ContT (Action m) m a] -> ContT (Action m) m ()
fork processes = ContT $ \next -> Fork <$> sequenceA (next () : [ process $ const $ pure $ Const | ContT process <- processes ])

How would I implement shared variables like IORefs or MVars? Or at least an async/await mechanism? Bonus points if it's polymorphic in the type of data passed.

Jon Purdy

I assume by “implement shared variables like IORefs or MVars” you mean in a way other than just having the underlying monad m include IO and using IORef/MVar. That’s straightforward, something like this:

newVar :: a -> ContT (Action IO) IO (IORef a)
newVar x = ContT $ \ k -> Atom $ do
  v <- newIORef x
  pure $ k v

A conventional way to add mutable variables to the “poor man’s concurrency monad” purely is by adding additional actions to the Action type for creating, reading, and writing mutable variables. Suppose we have some type Var m a that identifies mutable variables of type a that can be created & accessed in m.

data Action m where
  Atom :: m (Action m) -> Action m
  Fork :: [Action m] -> Action m
  Stop :: Action m

  New   :: (Var m a -> Action m) -> Action m
  Read  :: Var m a -> (a -> Action m) -> Action m
  Write :: Var m a -> a -> Action m -> Action m

Notice that the type parameter a does not appear in the result type of these new constructors, so it’s existentially quantified, and variables may thus contain values of any type. New is an action that continues to another action with a fresh variable as an argument; Read, given a variable, continues to the next action with that variable’s value; and Write, given a variable and a new value, writes the value into the variable before continuing.

Like fork, these would be constructed with helper functions that produce actions in ContT (Action m) m:

newVar
  :: (Applicative m)
  => ContT (Action m) m (Var m a)
newVar = ContT $ \ k -> pure (New (Atom . k))

readVar
  :: (Applicative m)
  => Var m a -> ContT (Action m) m a
readVar v = ContT $ \ k -> pure (Read v (Atom . k))

writeVar
  :: (Applicative m)
  => Var m a -> a -> ContT (Action m) m ()
writeVar v x = ContT $ \ k -> pure (Write v x (Atom (k ())))

After that, you just have to decide on a suitable representation of Var. One method is a data family, which makes it relatively easy to use IORef/MVar when IO is available, and something else like an Int index into an IntMap otherwise.

data family Var (m :: Type -> Type) (a :: Type) :: Type

data instance Var IO a = IOVar { unIOVar :: !(MVar a) }

Of course this is just a sketch; a much more fleshed out implementation can be found in the monad-par package, whose design is described in A Monad for Deterministic Parallelism (Marlow, Newton, & Peyton Jones 2011); its Par monad is basically a continuation monad around an action type like this, and its IVar abstraction is implemented similarly to this, with some additional constraints like extra strictness to enforce determinism and allow pure execution of internally impure code (an IVar secretly wraps an IORef).

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

How to it make pure?

分類Dev

How would you make a monad instance of this coroutine?

分類Dev

How to set global variables in Citrus in pure java?

分類Dev

How can I make this menu pure CSS?

分類Dev

LLVM - How to make a nested function see an outside function's variables

分類Dev

How to prompt user for [y/n] in my makefile (with pure make syntaxis)?

分類Dev

How to make a queued message broker in pure C#

分類Dev

Unable to understand how State Monad get it's state in this code

分類Dev

How to zoom a monad transformer?

分類Dev

How can I make a weak protocol reference in 'pure' Swift (without @objc)

分類Dev

How to programmatically set variables in Ionic's variables.scss?

分類Dev

Is there a Monad which collects results and `mappend`s them?

分類Dev

How to use multiple variables in Rust's for loop?

分類Dev

How can we make 'static' variables Thread-Safe in swift?

分類Dev

How can we make 'static' variables Thread-Safe in swift?

分類Dev

How to make buttons execute the same code but with different variables accordingly?

分類Dev

How to make a radar chart using python with data stored in variables

分類Dev

How to make .env variables work inside JS class constructors?

分類Dev

How to make a package set up protected variables in R?

分類Dev

How to make class variables persist between modules in VBA

分類Dev

How do I make sudo preserve my environment variables?

分類Dev

How to make another batch file with variables using batch?

分類Dev

How to make my db variables global for my class (php)

分類Dev

Python: How to make variables consistent throughout different functions?

分類Dev

How to make UICollectionView's height autoresizable and scrollable?

分類Dev

How to make Laravel's Validator $rules optional?

分類Dev

How to make the environment variables reach Dataflow workers as environment variables in python sdk

分類Dev

How to create a monad that combines state and error in Haskell

分類Dev

How to implement the `List` monad transformer in Scala?

Related 関連記事

  1. 1

    How to it make pure?

  2. 2

    How would you make a monad instance of this coroutine?

  3. 3

    How to set global variables in Citrus in pure java?

  4. 4

    How can I make this menu pure CSS?

  5. 5

    LLVM - How to make a nested function see an outside function's variables

  6. 6

    How to prompt user for [y/n] in my makefile (with pure make syntaxis)?

  7. 7

    How to make a queued message broker in pure C#

  8. 8

    Unable to understand how State Monad get it's state in this code

  9. 9

    How to zoom a monad transformer?

  10. 10

    How can I make a weak protocol reference in 'pure' Swift (without @objc)

  11. 11

    How to programmatically set variables in Ionic's variables.scss?

  12. 12

    Is there a Monad which collects results and `mappend`s them?

  13. 13

    How to use multiple variables in Rust's for loop?

  14. 14

    How can we make 'static' variables Thread-Safe in swift?

  15. 15

    How can we make 'static' variables Thread-Safe in swift?

  16. 16

    How to make buttons execute the same code but with different variables accordingly?

  17. 17

    How to make a radar chart using python with data stored in variables

  18. 18

    How to make .env variables work inside JS class constructors?

  19. 19

    How to make a package set up protected variables in R?

  20. 20

    How to make class variables persist between modules in VBA

  21. 21

    How do I make sudo preserve my environment variables?

  22. 22

    How to make another batch file with variables using batch?

  23. 23

    How to make my db variables global for my class (php)

  24. 24

    Python: How to make variables consistent throughout different functions?

  25. 25

    How to make UICollectionView's height autoresizable and scrollable?

  26. 26

    How to make Laravel's Validator $rules optional?

  27. 27

    How to make the environment variables reach Dataflow workers as environment variables in python sdk

  28. 28

    How to create a monad that combines state and error in Haskell

  29. 29

    How to implement the `List` monad transformer in Scala?

ホットタグ

アーカイブ