Created
January 5, 2018 06:06
-
-
Save bkase/5563d09841b0b236ce645543929f50d2 to your computer and use it in GitHub Desktop.
Callback-based Effects (ported from Swift Sandbox)
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
/* | |
* A callback-base implementation of effectful computation that defers interpretation | |
* until after computation is expressed (so you can inject different interpreters | |
* onto the same computation). | |
* | |
* The downside is the results aren't expressed as values. They are callback calls. | |
* You probably don't actually want to use this, but it seems interesting to think about. | |
* | |
* Inspired by "Programming with Algebraic Effects and Handlers" by | |
* Andrej Bauer and Matija Pretnar 2012 | |
* | |
* Tested on Swift 3.1.1 | |
* bkase @ 2017 | |
*/ | |
// An effectful computation | |
// An effect handler takes some input and a sink and performs some effect to feed the sink some output based on the input zero or more times | |
typealias EffectHandler<I,O> = (I, (O) -> ()) -> () | |
// A callback | |
typealias Callback<O> = (O) -> () | |
// An effectful computation needs a handler and a sink to feed output | |
// By binding the handler later, we can reuse the same effectful computation | |
// but interpret the effects differently. | |
struct Effectful<EffIn,EffOut,Out> { | |
let handle: (@escaping EffectHandler<EffIn, EffOut>) -> (Callback<Out>) -> () | |
} | |
// Nondeterministic choice as an effect | |
let effectful = Effectful<[Int],Int,Int> { decide in { next in | |
decide([0,5,8]) { y in | |
decide([10,20]) { x in | |
next(x - y) | |
} | |
} | |
} } | |
// Choose interpreter later | |
let chooseFirst = effectful.handle { choices, k in k(choices[0]) } | |
let chooseAll = effectful.handle { choices, k in | |
choices.forEach{ k($0) } | |
} | |
func toStdout<T>(t: T) -> () { print("\(t)") } | |
print("Choose first") | |
chooseFirst(toStdout) | |
print("Choose all") | |
chooseAll(toStdout) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment