{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
module Chapter06 () where
import Data.Void (absurd)
-- takes a function that accepts any possible a
applyToFive :: (forall a. a -> a) -> Int
applyToFive f = f 5
p :: Int -> (forall a. (a -> a))
p b = id
p1 :: (a -> b) -> (forall c. c -> a) -> b
p1 a b = (a . b) absurd
type A a = a
type B a r = (forall r. (a -> r) -> r)
from :: A a -> B a r
from a b = b a
to :: B a r -> A a
to b = b id
(to . from) x =
= to (from x)
= (from x) id
= (\b -> b x) id
= id x
= x
(from . to) x =
= from (to x)
= from (x id)
= \b -> b (x id)
= \b -> b ((\s -> s (a :: a)) id)
= \b -> b (a :: a)
newtype Cont a = Cont {unCont :: forall r. (a -> r) -> r}
instance Functor Cont where
fmap f (Cont a) = Cont $ \x -> a $ x . f
-- fmap f (Cont a) = Cont $ \x -> a $ \y -> x $ f y
instance Applicative Cont where
pure a = Cont $ \x -> x a
(Cont a) <*> (Cont b) = Cont $ \x -> a $ \y -> b (x . y)
instance Monad Cont where
return = pure
(Cont a) >>= f = Cont $ \x -> a (\y -> unCont (f y) x)
(Cont a) <*> (Cont b) = Cont $ \x -> a $ \y -> b $ \z -> x (y z)
(Cont a) <*> (Cont b) = Cont $ \x -> a $ \y -> b $ \z -> (x . y) z
\z -> x (y z) =
x . y
withVersionNumber :: (Double -> r) -> r
withVersionNumber f = f 1.0
withTimestamp :: (Int -> r) -> r
withTimestamp f = f 1532083362
withOS :: (String -> r) -> r
withOS f = f "linux"
releaseStringCont :: String
releaseStringCont = flip unCont id $ do
version <- Cont withVersionNumber
date <- Cont withTimestamp
os <- Cont withOS
return $ os ++ "-" ++ show version ++ "-" ++ show date
newtype ContT r m a = ContT {unContT :: (a -> m r) -> m r}
instance (Functor m) => Functor (ContT r m) where
fmap f (ContT a) = ContT $ \x -> a $ x . f
instance (Functor m) => Applicative (ContT r m) where
pure x = ContT $ \y -> y x
(ContT a) <*> (ContT b) = ContT $ \x -> a $ \y -> b (x . y)