{-# LANGUAGE RankNTypes #-}
module Cps
(
CPS (..)
, toCPS
, fromCPS
, addCont
, addOne
, pythagorasCont
, releaseString
, releaseStringCPS
, squareCont
, withOS
, withTimestamp
, withVersionNumber
) where
import Control.Monad.Trans.Cont (Cont, callCC)
toCPS :: a -> (forall r. (a -> r) -> r)
toCPS :: forall a. a -> forall r. (a -> r) -> r
toCPS = ((a -> r) -> a -> r) -> a -> (a -> r) -> r
forall a b c. (a -> b -> c) -> b -> a -> c
flip (a -> r) -> a -> r
forall a b. (a -> b) -> a -> b
($)
fromCPS :: (forall r. (a -> r) -> r) -> a
fromCPS :: forall a. (forall r. (a -> r) -> r) -> a
fromCPS = (((a -> a) -> a) -> (a -> a) -> a
forall a b. (a -> b) -> a -> b
$ a -> a
forall a. a -> a
id)
addCont :: Int -> Int -> Cont r Int
addCont :: forall r. Int -> Int -> Cont r Int
addCont Int
x Int
y = ((Int -> ContT r Identity Int) -> ContT r Identity Int)
-> ContT r Identity Int
forall {k} a (r :: k) (m :: k -> *) b.
((a -> ContT r m b) -> ContT r m a) -> ContT r m a
callCC (((Int -> ContT r Identity Int) -> ContT r Identity Int)
-> ContT r Identity Int)
-> ((Int -> ContT r Identity Int) -> ContT r Identity Int)
-> ContT r Identity Int
forall a b. (a -> b) -> a -> b
$ \Int -> ContT r Identity Int
k -> Int -> ContT r Identity Int
k (Int
x Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
y)
squareCont :: Int -> Cont r Int
squareCont :: forall r. Int -> Cont r Int
squareCont Int
x = ((Int -> ContT r Identity Int) -> ContT r Identity Int)
-> ContT r Identity Int
forall {k} a (r :: k) (m :: k -> *) b.
((a -> ContT r m b) -> ContT r m a) -> ContT r m a
callCC (((Int -> ContT r Identity Int) -> ContT r Identity Int)
-> ContT r Identity Int)
-> ((Int -> ContT r Identity Int) -> ContT r Identity Int)
-> ContT r Identity Int
forall a b. (a -> b) -> a -> b
$ \Int -> ContT r Identity Int
k -> Int -> ContT r Identity Int
k (Int
x Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
x)
pythagorasCont :: Int -> Int -> Cont r Int
pythagorasCont :: forall r. Int -> Int -> Cont r Int
pythagorasCont Int
x Int
y = do
Int
x_squared <- Int -> Cont r Int
forall r. Int -> Cont r Int
squareCont Int
x
Int
y_squared <- Int -> Cont r Int
forall r. Int -> Cont r Int
squareCont Int
y
Int -> Int -> Cont r Int
forall r. Int -> Int -> Cont r Int
addCont Int
x_squared Int
y_squared
newtype CPS a = CPS { forall a. CPS a -> forall r. (a -> r) -> r
runCPS :: forall r. (a -> r) -> r}
instance Functor CPS where
fmap :: forall a b. (a -> b) -> CPS a -> CPS b
fmap a -> b
f (CPS forall r. (a -> r) -> r
g) = (forall r. (b -> r) -> r) -> CPS b
forall a. (forall r. (a -> r) -> r) -> CPS a
CPS ((forall r. (b -> r) -> r) -> CPS b)
-> (forall r. (b -> r) -> r) -> CPS b
forall a b. (a -> b) -> a -> b
$ \b -> r
k -> (a -> r) -> r
forall r. (a -> r) -> r
g (b -> r
k (b -> r) -> (a -> b) -> a -> r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> b
f)
instance Applicative CPS where
pure :: forall a. a -> CPS a
pure a
a = (forall r. (a -> r) -> r) -> CPS a
forall a. (forall r. (a -> r) -> r) -> CPS a
CPS ((a -> r) -> a -> r
forall a b. (a -> b) -> a -> b
$ a
a)
(CPS forall r. ((a -> b) -> r) -> r
f) <*> :: forall a b. CPS (a -> b) -> CPS a -> CPS b
<*> (CPS forall r. (a -> r) -> r
g) = (forall r. (b -> r) -> r) -> CPS b
forall a. (forall r. (a -> r) -> r) -> CPS a
CPS ((forall r. (b -> r) -> r) -> CPS b)
-> (forall r. (b -> r) -> r) -> CPS b
forall a b. (a -> b) -> a -> b
$ \b -> r
k -> ((a -> b) -> r) -> r
forall r. ((a -> b) -> r) -> r
f (\a -> b
a -> (a -> r) -> r
forall r. (a -> r) -> r
g (b -> r
k (b -> r) -> (a -> b) -> a -> r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> b
a))
instance Monad CPS where
(CPS forall r. (a -> r) -> r
g) >>= :: forall a b. CPS a -> (a -> CPS b) -> CPS b
>>= a -> CPS b
f = (forall r. (b -> r) -> r) -> CPS b
forall a. (forall r. (a -> r) -> r) -> CPS a
CPS ((forall r. (b -> r) -> r) -> CPS b)
-> (forall r. (b -> r) -> r) -> CPS b
forall a b. (a -> b) -> a -> b
$ \b -> r
k -> (a -> r) -> r
forall r. (a -> r) -> r
g (\a
a -> CPS b -> forall r. (b -> r) -> r
forall a. CPS a -> forall r. (a -> r) -> r
runCPS (a -> CPS b
f a
a) b -> r
k)
addOne :: Int -> Int
addOne :: Int -> Int
addOne Int
x = Int
x Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
withVersionNumber :: (Double -> r) -> r
withVersionNumber :: forall r. (Double -> r) -> r
withVersionNumber Double -> r
f = Double -> r
f Double
0.1
withTimestamp :: (Int -> r) -> r
withTimestamp :: forall r. (Int -> r) -> r
withTimestamp Int -> r
f = Int -> r
f Int
1532083362
withOS :: (String -> r) -> r
withOS :: forall r. (String -> r) -> r
withOS String -> r
f = String -> r
f String
"linux"
releaseString :: String
releaseString :: String
releaseString =
(String -> String) -> String
forall r. (String -> r) -> r
withOS ((String -> String) -> String) -> (String -> String) -> String
forall a b. (a -> b) -> a -> b
$ \String
os ->
(Double -> String) -> String
forall r. (Double -> r) -> r
withVersionNumber ((Double -> String) -> String) -> (Double -> String) -> String
forall a b. (a -> b) -> a -> b
$ \Double
version ->
(Int -> String) -> String
forall r. (Int -> r) -> r
withTimestamp ((Int -> String) -> String) -> (Int -> String) -> String
forall a b. (a -> b) -> a -> b
$ \Int
timestamp ->
String
os String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"-v" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Double -> String
forall a. Show a => a -> String
show Double
version String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"-" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
timestamp
releaseStringCPS :: CPS String
releaseStringCPS :: CPS String
releaseStringCPS = do
String
os <- (forall r. (String -> r) -> r) -> CPS String
forall a. (forall r. (a -> r) -> r) -> CPS a
CPS (String -> r) -> r
forall r. (String -> r) -> r
withOS
Double
version <- (forall r. (Double -> r) -> r) -> CPS Double
forall a. (forall r. (a -> r) -> r) -> CPS a
CPS (Double -> r) -> r
forall r. (Double -> r) -> r
withVersionNumber
Int
timestamp <- (forall r. (Int -> r) -> r) -> CPS Int
forall a. (forall r. (a -> r) -> r) -> CPS a
CPS (Int -> r) -> r
forall r. (Int -> r) -> r
withTimestamp
String -> CPS String
forall a. a -> CPS a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (String -> CPS String) -> String -> CPS String
forall a b. (a -> b) -> a -> b
$ String
os String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"-v" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Double -> String
forall a. Show a => a -> String
show Double
version String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"-" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
timestamp