An Algebraic Effect System for Golang.

Stop stores continuation

+32 -13
+1 -1
abort/result.go
··· 13 13 var err Result[V, E] 14 14 var abortFn AbortFn[E] = func(e E) fx.FxNil { 15 15 err = failure[V](e) 16 - return fx.Stop[fx.Nil, fx.Nil]() 16 + return fx.Halt[fx.Nil, fx.Nil]() 17 17 } 18 18 succeeded := fx.Map(fx.ProvideLeft(e, abortFn), success[V, E]) 19 19 failed := func() fx.FxPure[Result[V, E]] { return fx.Pure(err) }
+31 -12
fx.go
··· 3 3 type Fx[S, V any] struct { 4 4 imm func() V 5 5 sus func(S) Fx[S, V] 6 - stp func() 6 + stp func(any) Fx[S, V] 7 7 } 8 8 9 9 type FxPure[V any] = Fx[Nil, V] ··· 29 29 30 30 func Ctx[V any]() Fx[V, V] { return Func(identity[V]) } 31 31 32 - func Stop[S, V any]() Fx[S, V] { return Fx[S, V]{stp: func() {}} } 32 + // An stopped effect that panics if restarted 33 + func Halt[S, V any]() Fx[S, V] { 34 + return Stop(func(x any) Fx[S, V] { 35 + panic("tried to restart halted effect. try using fx.Replace instead") 36 + }) 37 + } 38 + 39 + func Stop[S, V any](f func(any) Fx[S, V]) Fx[S, V] { return Fx[S, V]{stp: f} } 33 40 34 41 // Replace with y if x is already stopped. Otherwise x continues. 35 42 func Replace[S, V any](y func() Fx[S, V]) func(Fx[S, V]) Fx[S, V] { ··· 48 55 func Cont[T, U, S, V any](cmap func(T) S, fmap func(V) Fx[T, U]) func(Fx[S, V]) Fx[T, U] { 49 56 return func(e Fx[S, V]) Fx[T, U] { 50 57 if e.stp != nil { 51 - return Stop[T, U]() 58 + return Stop(func(x any) Fx[T, U] { 59 + return Cont(cmap, fmap)(e.stp(x)) 60 + }) 52 61 } 53 62 if e.imm != nil { 54 63 return fmap(e.imm()) ··· 80 89 func ContraMap[V, S, R any](f func(R) S) func(Fx[S, V]) Fx[R, V] { 81 90 return func(e Fx[S, V]) Fx[R, V] { 82 91 if e.stp != nil { 83 - return Stop[R, V]() 92 + return Stop(func(x any) Fx[R, V] { 93 + return ContraMap[V](f)(e.stp(x)) 94 + }) 84 95 } 85 96 if e.imm != nil { 86 97 return Const[R](e.imm()) ··· 161 172 162 173 func ProvideLeft[A, B, V any](e Fx[And[A, B], V], a A) Fx[B, V] { 163 174 if e.stp != nil { 164 - return Stop[B, V]() 175 + return Stop(func(x any) Fx[B, V] { 176 + return ProvideLeft(e.stp(x), a) 177 + }) 165 178 } 166 179 if e.imm != nil { 167 180 return Const[B](e.imm()) 168 181 } 169 182 return Pending(func(b B) Fx[B, V] { 170 183 var ab And[A, B] = func() (A, B) { return a, b } 171 - for { 172 - e = e.sus(ab) 173 - if e.stp != nil { 174 - return Stop[B, V]() 175 - } 176 - if e.imm != nil { 177 - return Const[B](e.imm()) 184 + var loop func(e Fx[And[A, B], V]) Fx[B, V] 185 + loop = func(e Fx[And[A, B], V]) Fx[B, V] { 186 + for { 187 + e = e.sus(ab) 188 + if e.stp != nil { 189 + return Stop(func(x any) Fx[B, V] { 190 + return loop(e.stp(x)) 191 + }) 192 + } 193 + if e.imm != nil { 194 + return Const[B](e.imm()) 195 + } 178 196 } 179 197 } 198 + return loop(e) 180 199 }) 181 200 } 182 201