Skip to content

Instantly share code, notes, and snippets.

@71
Created February 7, 2020 23:08
Show Gist options
  • Save 71/8e4f0798137862a07b37e4e080be0ab7 to your computer and use it in GitHub Desktop.
Save 71/8e4f0798137862a07b37e4e080be0ab7 to your computer and use it in GitHub Desktop.
Trying to implement algebraic effects in Go.
// Inspired by https://github.com/ocamllabs/ocaml-effects-tutorial
//
// Goroutines can be implemented using effects, and, as it turns
// out, effects can be implemented using Goroutines.
// It does require an explicit `context.Context` argument, though.
//
// Note: The following code is a quick and dirty experiment. It
// is not efficient, and probably leaks memory.
package main
import (
"fmt"
"context"
)
type Continuation func(x interface{})
type Handler func(k Continuation, args ...interface{})
type eff struct {
ch chan interface{}
handler Handler
}
func Perform(ctx context.Context, effectType interface{}, values ...interface{}) interface{} {
effectObj := ctx.Value(effectType).(eff)
go func() {
effectObj.handler(func(x interface{}) {
effectObj.ch <- x
}, values...)
}()
return <-effectObj.ch
}
func WithHandler(ctx context.Context, effectType interface{}, handler Handler) context.Context {
ch := make(chan interface{})
return context.WithValue(ctx, effectType, eff{ch, handler})
}
type get struct {}
type put struct {}
var (
getEffect = &get{}
putEffect = &put{}
)
func GetState(ctx context.Context) interface{} {
return Perform(ctx, getEffect)
}
func PutState(ctx context.Context, x interface{}) {
Perform(ctx, putEffect, x)
}
func WithState(ctx context.Context, state interface{}) context.Context {
ctx = WithHandler(ctx, getEffect, func(k Continuation, _ ...interface{}) {
k(state)
})
ctx = WithHandler(ctx, putEffect, func(k Continuation, args ...interface{}) {
state = args[0]
k(nil)
})
return ctx
}
func main() {
ctx := WithState(context.Background(), 5)
fmt.Println("State:", GetState(ctx))
PutState(ctx, 10)
fmt.Println("State:", GetState(ctx))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment