Skip to content

Instantly share code, notes, and snippets.

@sgf-dma
Created August 21, 2024 21:28
Show Gist options
  • Save sgf-dma/06ba1a9e99c995cd79cc226e8a575548 to your computer and use it in GitHub Desktop.
Save sgf-dma/06ba1a9e99c995cd79cc226e8a575548 to your computer and use it in GitHub Desktop.
cps version of 'reverse' for comparison with Go version in revCps.go.
import Control.Monad.Trans.Cont
import Data.Function
data R a = R (R a) | E a
-- This function is called from 'shift' and 'shift' returns immediately
-- (without calling further continuation) because result is already here - 'R'
-- value. Continuation 'k' will be called later, when evaluation of returned
-- 'R' value is forced in 'run'.
step :: a -> [a] -> ([a] -> R [a]) -> Cont (R [a]) (R [a])
step x xs k = return $ R (k (x : xs))
reverseCps :: [a] -> R [a]
reverseCps xs = flip runCont id -- Go: m(nil)
-- $ foldr (\x m zs -> shift (step x zs) >>= m)
$ foldr -- Go: for _, x := range xs
(\x m -> \zs -> m =<< (shift (step x zs))) -- Go: m = func (k Cont) Cont {..}
(return . E) -- Go: return nil, []int
xs
[] -- Initial value of reversed list, Go: Either 'nil' in 'return m(nil)' or '[]int{}' in following 'return nil, []int{}'.
-- 'rec' is anonymous recursion supplied by 'fix'.
run :: (R [a] -> [a]) -> R [a] -> [a]
run rec (R z) = rec z
run rec (E z) = z
main :: IO ()
main = print
. fix run -- Go: for ; zs == nil; f, zs = f()
$ reverseCps [1..5]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment