summaryrefslogtreecommitdiff
path: root/doc/todo/Add_MonadBaseControl_instance_to_Propellor/comment_3_45413e6e811c34edc38a6ff70ca7c208._comment
blob: 74a5c8bb08dfcd589c24c6af6e25955142c3b7a5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
[[!comment format=mdwn
 username="joey"
 subject="""comment 3"""
 date="2016-12-01T18:14:28Z"
 content="""
Looking at the lifted-async that is what uses the MonadBaseControl instance
in your use case, I have some concerns.

Its docs say "All the functions restore the monadic effects in the forked
computation unless specified otherwise." I think that has bearing on the
following situation:

Suppose that two Propellor monad actions are run concurrently by this:

	foo `concurrently` bar

Propellor's monad includes a Writer component, that accumulates [EndAction].
Since they are running concurrently, it seems likely that `foo` and `bar`
are using separate Writers. Propellor doesn't currently use a State monad,
but suppose that was added to its stack. Then `foo` and `bar` would
necessarily, I think, be manipulating independent copies of state.

Now, what happens when `concurrently` finishes running them? We have two
Writers and/or two States, that need to be merged somehow. I don't see
anything in the library that lets it do an intelligent merge. (For example,
it could notice that [EndAction] is a monoid and mappend the two values.)

So, I think when it says it's a restoring the monadic effects, it means it's
*discarding* any changes that might have been made to the Writer or State.

Is this a large problem for Propellor? Maybe not. EndActions rarely need to
be added, and in fact only one property in all of Propellor currently adds
an EndAction. But this could change; Propellor could get state in its
monad. What then?

Now, I actually dealt with this problem in the
Propellor.Property.Concurrent module. The code there threads the Writer
v alues through the concurrent actions and merges them at the end. If
MonadBaseControl provides a more principled way to do that, which lets
lifted-async also be used safely, then that part of propellor could perhaps
be changed to use it. 

But, I don't know if this is a problem that MonadBaseControl deals with at
all. It might be that its design is intended to be used for things like
`bracket`, where there's no concurrency, and so not as much problem with
getting different monadic states that need to be merged together. (Although
in `bracket foo bar baz`, if baz throws an exception part way through,
there's an interesting question about what to do with any monadic state it
may have accumulated.) 
"""]]