Comments (10)
I gather that the problem that you are highlighting is solely on the IO
implementation? Or does the same happen with, say StateT Maybe
?
What behaviour would you expect in case or errors?
from capability.
Sorry - I was mainly thinking about the situation for ReaderT IO
(and my mind didn't work very well yesterday), where I would expect a bracket
over the m
. This can be provided as a separate strategy on monads with MonadMask
.
I'm not entirely sure with the semantics in the case of using a transformer stack, but I can imagine something like this going wrong:
data M a = M { runM :: ExceptT () (State String) a }
deriving (Functor, Applicative, Monad, Mtl.MonadState String, Mtl.MonadError ())
deriving (HasSink "log" String, WriterLog "log" String)
via SinkLog (MonadState M)
deriving (HasThrow "err" ())
via MonadError m
f :: (Either () String, String)
f = runState (runExceptT $ runM $ tell "a" *> listen (tell "b" *> throw () *> tell "c")) ""
-- Expected: (Left (), "ab")
-- Actual: (Left (), "b")
disclaimer - I don't have my machine near me, and i haven't tested this. Feel free to ignore before I get home and do some experiment.
from capability.
The concurrency problem may not be worth fixing (in some sense), but at least it deserves a warning in the docs
HasState
, same as MTL's MonadState
, is not concurrency safe. In particular modify'
is implemented as
do s <- get
put $! f s
which is not atomic.
having no error recovery is arguably a larger problem.
This issue about HasMask
seems relevant to this question. I imagine that an exception safe version of this would require a bracket
of some sort.
from capability.
We could, presumably, implement modify'
using state
, though. And implement state
with modifyRef
, though this is not atomic on IORef
by default (which uses modifyIORef
, rather than atomicModifyIORef
.
That being said, I suppose that get >>= put
is safe with MVars
, so maybe we simply don't have to care about the concurrency part.
from capability.
That being said, I suppose that
get >>= put
is safe withMVars
, so maybe we simply don't have to care about the concurrency part.
Hmm, I might be misreading, but I don't see how. The following kind of interleaving is the issue I'm referring to, where modify'
is not atomic.
do s1 <- get |
| do s2 <- get
put $! f1 s1 |
| put $! f2 s2
We could, presumably, implement
modify'
usingstate
, though.
Can we? modify'
still needs to be strict in the MTL MonadState
case, where state
is just the underlying MTL state
. And, I presume, in general modify
(without '
) should still be non-strict.
from capability.
(Guessing) For MVar
s, it is possible that we implement modify
with takeMVar
and putMVar
in combination which will be atomic, since any other thread trying to read will be blocked. Apparently that is different from get >>= (put . f)
though.
from capability.
Hmm, I might be misreading, but I don't see how. The following kind of interleaving is the issue I'm referring to, where
modify'
is not atomic.
On MVar
that interleaving will just have s2
block on get
(well, unless get
is implemented as readMVar
rather than takeMVar
… which it probably is. Grumble.)
Can we? modify' still needs to be strict in the MTL MonadState case, where state is just the underlying MTL state. And, I presume, in general modify (without ') should still be non-strict.
It probably depends how state
is implemented. If the pair is used lazily (fst
, snd
), then we can't quite make it strict for State
. An alternative is to add a strict state'
primitive to the class.
But maybe we should focus on the behaviour with exception first.
from capability.
On
MVar
that interleaving will just haves2
block onget
(well, unlessget
is implemented asreadMVar
rather thantakeMVar
… which it probably is. Grumble.)
get
indeed uses readMVar
, and it has to, because sequencing get
, e.g. get >> get
, is allowed by the state API and is not expected to block indefinitely.
My impression is that MonadState
and thereby HasState
, which is based on the former, is just not designed for a concurrent use-case.
I believe we discussed a potential HasAtomicState
that could be designed for that use-case at some point in the past.
But maybe we should focus on the behaviour with exception first.
Agreed. Coming back to HasMask
, we could make such a capability a prerequisite of the WriterLog
instance. If needed we could provide the simpler UnmaskedWriterLog
without such a constraint.
from capability.
a potential HasAtomicState
What about introducing get_
and put_
as methods of HasState
too, allowing different semantics of get >>= put
and state
? Three operations can all be atomic, and modify
can be defined in terms of state
(thus also atomic).
from capability.
a potential HasAtomicState
What about introducing
get_
andput_
as methods ofHasState
too, allowing different semantics ofget >>= put
andstate
? Three operations can all be atomic, andmodify
can be defined in terms ofstate
(thus also atomic).
They are methods of HasState
's super-classes HasSource
and HasSink
already.
An advantage of a dedicated class would be that atomicity could be specified on the class, such that all instances must fulfill it. Meaning, all code using HasAtomicState
would be correct in a concurrent use-case. The trouble with making this a property of particular instances is that, in that case, code that is written with the constraint HasState => ...
might not be correct for some instances of HasState
.
from capability.
Related Issues (20)
- An alternative way of managing effects in `capability` HOT 4
- Capability focusing using lens? HOT 4
- HasMask capability
- Overlapping tags HOT 8
- Consider renaming library HOT 2
- Move all modules under a single namespace HOT 2
- Document Nix cache in README HOT 1
- `zoom`, `magnify`, and `wrapError` forget other capabilities
- Push haddocks to S3 from CI and link from README HOT 1
- Don't export class methods by default HOT 4
- Elimination methods in classes should be moved HOT 10
- Associate type to tags HOT 2
- `nix-shell` fails HOT 2
- GHC 8.8 compatible version
- Cannot Lift through Stream HOT 12
- Benchmark for Capability V.S. other effect handling libraries HOT 2
- Enclosing call to 'local' resets accumulated Writer value when the values share a record HOT 3
- Running effects locally HOT 13
- Is `derive` safe? HOT 6
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from capability.