import "fmt"
-// Haskell: data R a = R (R a) | E {unE :: a}
+// Haskell: data R a = R (R a) | E a
type R func() (R, []int)
// Haskell: Cont (R [a]) [a]
// 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 f = Cont $ \k -> runCont (f k) id
+// 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 (f k) id
+ return f(xs, k) // Haskell's shift: runCont (g k) id
}
}
return nil, []int{} // return . E
}
-func getResult(f R, zs []int) []int {
- for ; zs == nil; f, zs = f() { // Haskell: fix run
+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", getResult(reverseCps(xs)))
+ fmt.Printf("%v\n", runR(reverseCps(xs)))
}
--- /dev/null
+
+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)))
+}
+