Skip to content

Instantly share code, notes, and snippets.

@sgf-dma
Last active August 30, 2024 14:58
Show Gist options
  • Save sgf-dma/9e551fd9046c5bb640fee366ff61a4fd to your computer and use it in GitHub Desktop.
Save sgf-dma/9e551fd9046c5bb640fee366ff61a4fd to your computer and use it in GitHub Desktop.
cps version of function reversing slice compared with Haskell's revCps.hs
package main
import "fmt"
// Haskell: data R a = R (R a) | E a
type R func() (R, []int)
// Haskell: Cont (R [a]) [a]
type Cont func([]int) (R, []int)
func step(x int, xs []int, k Cont) (R, []int) {
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, []int) { // t is thunk.
return k(xs)
}
return t, nil
}
return nil, xs
}
// 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(f func([]int, Cont) (R, []int), k Cont) Cont {
return func (xs []int) (R, []int) {
return f(xs, k) // Haskell's shift: runCont (g k) id
}
}
func reverseCps(xs0 []int) (R, []int) {
var m Cont // Haskell: Cont (R [a]) [a]
for _, x := range xs0 { // Haskell: foldr .. xs
/*
m = func (k Cont) Cont { // Haskell: shift .. >>= m
return func (xs []int) (R, []int) {
return step(x, xs, k) // Haskell: runCont (f k) id
}
}(m) // Capture current m
*/
stepX := func (xs []int, k Cont) (R, []int) { return step(x, xs, k) } // Haskell: step x
// It's not a real 'Cont' though, because there is no >>=. Monads
// composition is done manually here. For real 'Cont' see cont.go.
m = shift(stepX, m) // Haskell: \zs -> m =<< (shift (step x zs))
}
if m != nil {
// Unwrap Cont.
return m(nil) // flip runCont id
}
return nil, []int{} // return . E
}
func runR(f R, zs []int) []int {
for ; f != nil; f, zs = f() { // Haskell: fix run
fmt.Printf("Iterate..\n")
}
return zs
}
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