1 {-# LANGUAGE Rank2Types #-}
2 module Distribution
.Solver
.Modular
.RetryLog
14 import Distribution
.Solver
.Compat
.Prelude
17 import Distribution
.Solver
.Modular
.Message
18 import Distribution
.Solver
.Types
.Progress
20 -- | 'Progress' as a difference list that allows efficient appends at failures.
21 newtype RetryLog step
fail done
= RetryLog
{
22 unRetryLog
:: forall fail2
. (fail -> Progress step fail2 done
)
23 -> Progress step fail2 done
26 -- | /O(1)/. Convert a 'RetryLog' to a 'Progress'.
27 toProgress
:: RetryLog step
fail done
-> Progress step
fail done
28 toProgress
(RetryLog f
) = f Fail
30 -- | /O(N)/. Convert a 'Progress' to a 'RetryLog'.
31 fromProgress
:: Progress step
fail done
-> RetryLog step
fail done
32 fromProgress l
= RetryLog
$ \f -> go f l
34 go
:: (fail1
-> Progress step fail2 done
)
35 -> Progress step fail1 done
36 -> Progress step fail2 done
37 go _
(Done d
) = Done d
38 go f
(Fail failure
) = f failure
39 go f
(Step m ms
) = Step m
(go f ms
)
41 -- | /O(1)/. Apply a function to the failure value in a log.
42 mapFailure
:: (fail1
-> fail2
)
43 -> RetryLog step fail1 done
44 -> RetryLog step fail2 done
45 mapFailure f l
= retry l
$ \failure
-> RetryLog
$ \g
-> g
(f failure
)
47 -- | /O(1)/. If the first log leads to failure, continue with the second.
48 retry
:: RetryLog step fail1 done
49 -> (fail1
-> RetryLog step fail2 done
)
50 -> RetryLog step fail2 done
51 retry
(RetryLog f
) g
=
52 RetryLog
$ \extendLog
-> f
$ \failure
-> unRetryLog
(g failure
) extendLog
54 -- | /O(1)/. Create a log with one message before a failure.
55 failWith
:: step
-> fail -> RetryLog step
fail done
56 failWith m failure
= RetryLog
$ \f -> Step m
(f failure
)
58 -- | /O(1)/. Create a log with one message before a success.
59 succeedWith
:: step
-> done
-> RetryLog step
fail done
60 succeedWith m d
= RetryLog
$ const $ Step m
(Done d
)
62 -- | /O(1)/. Prepend a message to a log.
64 -> RetryLog step
fail done
65 -> RetryLog step
fail done
66 continueWith m
(RetryLog f
) = RetryLog
$ Step m
. f
68 -- | /O(1)/. Prepend the given message and 'Enter' to the log, and insert
69 -- 'Leave' before the failure if the log fails.
70 tryWith
:: Message
-> RetryLog Message
fail done
-> RetryLog Message
fail done
72 RetryLog
$ Step m
. Step Enter
. unRetryLog
(retry f
(failWith Leave
))