An Algebraic Effect System for Golang.
1package fx
2
3// Creates an stopped effect from a resume function
4func Stop[S, V any](e func() Fx[S, V]) Fx[S, V] {
5 return Fx[S, V]{res: e}
6}
7
8// Resume an effect if it was previously stopped.
9func Resume[S, V any](e Fx[S, V]) Fx[S, V] {
10 if e.res != nil {
11 return e.res()
12 }
13 if e.imm != nil {
14 return Const[S](e.imm())
15 }
16 return Pending(func(s S) Fx[S, V] { return Resume(e.sus(s)) })
17}
18
19// Replace with y if x is already Halted. Otherwise x continues.
20func Replace[S, V any](y func() Fx[S, V]) func(Fx[S, V]) Fx[S, V] {
21 return func(x Fx[S, V]) Fx[S, V] {
22 if x.res != nil {
23 return y()
24 }
25 if x.imm != nil {
26 return Const[S](x.imm())
27 }
28 return Pending(func(s S) Fx[S, V] { return Replace(y)(x.sus(s)) })
29 }
30}
31
32// An stopped effect that panics if resumed.
33// Only useful with Replace.
34//
35// For example, an Abort effect halts since it has no possible value for V
36// but then its Handler can Replace the halted effect with an Error value.
37// See: abort/result.go
38func Halt[S, V any]() Fx[S, V] {
39 return Stop(func() Fx[S, V] {
40 return Fx[S, V]{
41 imm: func() V {
42 panic("tried to Resume a halted effect. try using Replace instead")
43 },
44 }
45 })
46}