Skip to content

Instantly share code, notes, and snippets.

@sgf-dma
Created August 26, 2024 17:44
Show Gist options
  • Save sgf-dma/40107a2ef278dca7c53797c6a3b81211 to your computer and use it in GitHub Desktop.
Save sgf-dma/40107a2ef278dca7c53797c6a3b81211 to your computer and use it in GitHub Desktop.
revCps.go version with generics.
package main
import "fmt"
// Haskell: data R a = R (R a) | E a
type R [Result any] func() (R[Result], Result)
// Haskell: Cont (R Result) T
type Cont [T any, Result any] func(T) (R[Result], Result)
// Type of function in shift, just a shortcut. See note below about this
// 'shift' and Haskell's 'shift' differences.
type shiftFunc [T any, Result any] func(T, Cont[T, Result]) (R[Result], Result)
// Haskell: In fact, this is '>>= \zs -> shift (f zs)' in foldr, which is
// hidden behind 'm'. For reference, haskell shift implementation:
// shift :: ((a -> r) -> Cont r r) -> Cont r a
// shift g = Cont $ \k -> runCont (g k) id
func shift[T any, Result any](f shiftFunc[T, Result], k Cont[T, Result]) Cont[T, Result] {
return func (xs T) (R[Result], Result) {
return f(xs, k) // Haskell's shift: runCont (g k) id
}
}
func runR[Result any](f R[Result], zs Result) Result {
for ; f != nil; f, zs = f() { // Haskell: fix run
fmt.Printf("Iterate..\n")
}
return zs
}
// step builds reverse slice in xs, but the final result is string
// representation of reverse slice. Well, this is just for more easily
// distinguishing result type from type passed along the monadic chain.
func step(x int, xs []int, k Cont[[]int, string]) (R[string], string) {
fmt.Printf("Got x = %v, xs = %v, k = %v\n", x, xs, k)
xs = append(xs, x)
if k != nil { // Preserve nil.
// Haskell: R (k (x : xs))
t := func() (R[string], string) { // t is thunk.
return k(xs)
}
return t, ""
}
return nil, fmt.Sprintf("%v", xs)
}
func reverseCps(xs0 []int) (R[string], string) {
// Build reverse slice into slice in monadic chain, but return result as a
// its string representation.
var m Cont[[]int, string] // Haskell: Cont (R [a]) [a]
for _, x := range xs0 { // Haskell: foldr .. xs
stepX := func (xs []int, k Cont[[]int, string]) (R[string], string) { return step(x, xs, k) } // Haskell: step x
m = shift(stepX, m) // Haskell: \zs -> m =<< (shift (step x zs))
}
if m != nil {
// Unwrap Cont.
return m(nil) // flip runCont id
}
return nil, "" // return . E
}
func main() {
xs := []int{1, 2, 3, 4}
fmt.Printf("%v\n", runR(reverseCps(xs)))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment