Created
August 26, 2024 17:44
-
-
Save sgf-dma/40107a2ef278dca7c53797c6a3b81211 to your computer and use it in GitHub Desktop.
revCps.go version with generics.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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