Pytanie zasadnicze:
Proszę o rozpiskę działania callCC tak na chłopski rozum.
A teraz w formie żali:
Najpierw może zapodam mój brudnopis z rozpiskami:
{-
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
return :: a -> m a
-}
newtype Cont r a = Cont { runCont :: ((a -> r) -> r) }
instance Monad (Cont r) where
return n = Cont (\k -> k n)
m >>= f = Cont (\k -> runCont m (\a -> runCont (f a) k))
class (Monad m) => MonadCont m where
callCC :: ((a -> m b) -> m a) -> m a
instance MonadCont (Cont r) where
callCC f = Cont $ \k -> runCont (f (\a -> Cont $ \_ -> k a)) k
{-
bar :: Cont r Int
bar = callCC $ \k -> do
let n = 5
k n
return 25
-}
bar :: Cont r Int
bar = callCC $ \k ->
k 5 >>= \_ ->
Cont (\k -> k 25)
{-
baz :: (Integer -> Cont r a) -> Cont r Integer
baz = \k ->
k 5 >>= \_ ->
Cont (\k -> k 25)
-}
baz :: (Integer -> Cont r a) -> Cont r Integer
--baz = \k -> Cont (\l -> runCont (k 5) (\a -> runCont ((\_ -> Cont (\k -> k 25)) a) l))
--baz = \k -> Cont (\l -> runCont (k 5) (\_ -> runCont (Cont (\k -> k 25)) l))
--baz = \k -> Cont (\l -> runCont (k 5) (\_ -> (\k -> k 25) l))
baz = \k -> Cont (\l -> runCont (k 5) (\_ -> l 25))
foo :: (Integer -> (a -> r) -> r) -> (Integer -> r) -> r
foo = \k l -> k 5 (\_ -> l 25)
boo :: (Integer -> r) -> r
--boo = callCC (\k -> Cont (\l -> runCont (k 5) (\_ -> l 25)))
--boo = \m -> ((\k l -> k 5 (\_ -> l 25)) (\a -> (\_ -> m a))) m
--boo = \m -> ((\k -> k 5 (\_ -> m 25)) (\a -> (\_ -> m a)))
--boo = \m -> ((\a -> (\_ -> m a)) 5 (\_ -> m 25))
--boo = \m -> ((\a _ -> m a) 5 (\_ -> m 25))
--boo = \m -> ((\a -> m a) 5)
boo = \m -> m 5
{-
-}
add x y = x + y
square x = x * x
add_cont :: Int -> Int -> Cont r Int
add_cont x y = return (add x y)
square_cont :: Int -> Cont r Int
square_cont x = return (square x)
{-
pythagoras_cont :: Int -> Int -> Cont r Int
pythagoras_cont x y =
do x_squared <- square_cont x
y_squared <- square_cont y
sum_of_squares <- add_cont x_squared y_squared
return sum_of_squares
-}
--m >>= f = Cont (\k -> runCont m (\a -> runCont (f a) k))
pythagoras_cont :: Int -> Int -> Cont r Int
--pythagoras_cont x y = square_cont x >>= (\x_squared -> square_cont y >>= (\y_squared -> add_cont x_squared y_squared >>= (\sum_of_squares -> Cont (\k -> k sum_of_squares))))
--pythagoras_cont x y = square_cont x >>= (\x_squared -> square_cont y >>= (\y_squared -> (add_cont x_squared y_squared >>= (\sum_of_squares -> Cont (\k -> k sum_of_squares)))))
--pythagoras_cont x y = square_cont x >>= (\x_squared -> square_cont y >>= (\y_squared -> Cont (\l -> runCont (add_cont x_squared y_squared) (\a -> runCont ((\sum_of_squares -> Cont (\k -> k sum_of_squares)) a) l))))
--pythagoras_cont x y = square_cont x >>= (\x_squared -> square_cont y >>= (\y_squared -> Cont (\l -> runCont (add_cont x_squared y_squared) (\a -> runCont (Cont(\k -> k a)) l))))
--pythagoras_cont x y = square_cont x >>= (\x_squared -> square_cont y >>= (\y_squared -> Cont (\l -> runCont (add_cont x_squared y_squared) (\a -> l a))))
--pythagoras_cont x y = square_cont x >>= (\x_squared -> Cont (\k -> runCont (square_cont y) (\b -> runCont ((\y_squared -> Cont (\l -> runCont (add_cont x_squared y_squared) (\a -> l a))) b) k)))
--pythagoras_cont x y = square_cont x >>= (\x_squared -> Cont (\k -> runCont (square_cont y) (\b -> runCont (Cont (\l -> runCont (add_cont x_squared b) (\a -> l a))) k)))
--pythagoras_cont x y = Cont (\n -> runCont (square_cont x) (\c -> runCont ((\x_squared -> Cont (\k -> runCont (square_cont y) (\b -> runCont (Cont (\l -> runCont (add_cont x_squared b) (\a -> l a))) k))) c) n))
--pythagoras_cont x y = Cont (\n -> runCont (square_cont x) (\c -> runCont (Cont (\k -> runCont (square_cont y) (\b -> runCont (Cont (\l -> runCont (add_cont c b) (\a -> l a))) k))) n))
--pythagoras_cont x y = Cont (\n -> runCont (square_cont x) (\c -> runCont (Cont (\k -> runCont (square_cont y) (\b -> runCont (add_cont c b) (\a -> k a)))) n))
pythagoras_cont x y = Cont (\k -> runCont (square_cont x) (\c -> runCont (square_cont y) (\b -> runCont (add_cont c b) (\a -> k a))))
Sprawa jest taka. Rozumiem mniej więcej na czym polegają kontynuacje i jak działa monada do składania kontynuacji, natomiast za cholerę nie jestem w stanie zrozumieć jak działa funkcja callCC. Moja rozpiska metody bar potwierdza, że jak wywołam aktualną kontynuację w bloku do to następne funkcje nie zostaną wykonane. Tyle, że dalej nie potrafię sobie opracować jakichś analogii mniej abstrakcyjnych niż znaczki.