Last active
December 11, 2015 19:59
-
-
Save ocharles/556b35e3d16565cab457 to your computer and use it in GitHub Desktop.
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 Control.Monad.Trans | |
> import Control.Monad.Trans.Iter | |
The completely iterative free monad transformer lets us capture non-termination as an effect. Furthermore, it's a monad *transformer*, so we can add non-termination on top of other effects. | |
A convenient combinator is | |
> untilSuccess :: Monad m => m (Maybe a) -> IterT m a | |
> untilSuccess f = maybe (delay (untilSuccess f)) return =<< lift f | |
Given a effectful computation that may fail, we repeatedly run it until it succeeds. Of course, just trying the same thing over and over again isn't guaranteed to terminate, so we work under `IterT` to capture the non-termination. | |
Now given a computation that may fail | |
> data TargetHit | |
> launchMissles :: IO (Maybe TargetHit) | |
> launchMissles = putStrLn "Launching..." >> return Nothing | |
we have a few choices. | |
If we're certain that a computation will succeed, and we're willing to wait indefinitely, we can just `retract`: | |
> ultimatelyLaunchMissles :: IO TargetHit | |
> ultimatelyLaunchMissles = retract (untilSuccess launchMissles) | |
However, our time is often limited - so we can retry a limited number of times: | |
> tryAndLaunchMissles :: IO (Maybe TargetHit) | |
> tryAndLaunchMissles = retract (cutoff 10 (untilSuccess launchMissles)) | |
This will `launchMissles` at most 10 times, and give us back either `Nothing`, or the successful `TargetHit` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment