haskelltypescontinuationsnewtypetype-synonyms

Structuring continuation types?


I'm going over continuations and I've come across two different approaches to structuring continuation types:

newtype C r a = C {runC :: (a -> r) -> r}

exampleFunction :: String -> C Bool String
exampleFunction s = C $ \t -> if length s > 10 then t s else False

continuationFunction :: String -> Bool
continuationFunction s = True

main = do
 let suspendedFunc = exampleFunction "testing"
 let completedFunc = runC suspendedFunc $ continuationFunction

versus the approach taken in Poor Mans Concurrency:

type C r a = (a -> r) -> r

exampleFunction :: String -> C Bool String
exampleFunction s = \t -> if length s > 10 then t s else False

...

I understand that the latter approach doesn't use an explicit data constructor.

  1. What are the practical differences of these approaches?
  2. Will this impact when I try to use this over a general type with a monad? Such as:

    data Hole = Hole1 Int | Hole2 String
    
    type C r m a = (a -> m r) -> m r
    
    exampleFunction :: String -> C Bool Maybe Hole
    exampleFunction s = \t -> do
          x <- t (Hole1 11)
          y <- t (Hole2 "test")
          ...
    
    continuationFunction :: Hole -> Bool
    continuationFunction (Hole1 x) = False
    continuationFunction (Hole2 y) = True  
    

Solution

  • The differences are the usual differences between type and newtype.

    A type synonym is just a new name for an existing type. type synonyms can't be partially applied, because the compiler expands the definition during type checking. For example, this is no good, even with TypeSynonymInstances:

    type TypeCont r a = (a -> r) -> r
    
    instance Monad (TypeCont r) where  -- "The type synonym ‘TypeCont’ should have 2 arguments, but has been given 1"
        return x = ($ x)
        k >>= f = \q -> k (\x -> (f x) q)
    

    newtypes, while operationally equivalent to the types they wrap, are separate entities in the type system. This means that newtypes can be partially applied.

    newtype NewtypeCont r a = Cont { runCont :: (a -> r) -> r }
    
    instance Monad (NewtypeCont r) where
        return x = Cont ($ x)
        Cont k >>= f = Cont $ \q -> k (\x -> runCont (f x) q)