Last active
August 29, 2015 14:10
-
-
Save danidiaz/e9382127d1c4025b9845 to your computer and use it in GitHub Desktop.
A twist on this Gist: https://gist.github.com/ocharles/556b35e3d16565cab457. Retrying actions with delays using the iterative monad transformer. Requires free >= 4.10.0.1.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
> import Safe (readMay) | |
> import Control.Monad | |
> import Control.Monad.Trans | |
> import Control.Monad.Trans.Iter (delay,untilJust,IterT,retract,cutoff) | |
> import Control.Concurrent (threadDelay) | |
This is an action that may fail: | |
> maybeReadInteger :: IO (Maybe Integer) | |
> maybeReadInteger = liftM readMay (putStr ">" >> getLine) | |
This is an infinite sequece of "delays", of two seconds each: | |
> delays :: IterT IO a | |
> delays = forever (delay (lift (threadDelay (2*10^6)))) | |
This tries 4 times to read an integer: | |
> retryIntegerRead :: IO (Maybe Integer) | |
> retryIntegerRead = | |
> (retract . cutoff 4) (delays `mplus` untilJust maybeReadInteger) | |
`untilJust` turns `maybeReadInteger` into a computation that keeps retrying until it succeeds. | |
We "sum" that computation with the `delays` one. `mplus` for `IterT` | |
makes the two computations "race" each other, and returns the value of the one that finishes earlier. | |
Since we don't want to wait forever in case of repeated failures, we establish a cutoff of 4 and | |
then retract. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment