2017-02-17 6 views
6

Je vais sur continuations et je suis venu à travers deux approches différentes pour structurer les types de continuation:Structurer les types de continuation?

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 

par rapport à l'approche adoptée dans 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 

... 

Je comprends que cette dernière approche doesn n'utilisez pas un constructeur de données explicite.

  1. Quelles sont les différences pratiques de ces approches?
  2. Cela aura-t-il un impact lorsque j'essaierai de l'utiliser sur un type général avec une monade? Tels que:

    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 
    
+4

Les différences sont les différences habituelles entre 'type' et' newtype'. Les synonymes 'type' sont juste un nouveau nom pour un type existant; ils ne peuvent pas être appliqués partiellement et vous ne pouvez pas en faire une «instance» d'une classe. 'newtype's sont séparés des types qu'ils enveloppent et vous pouvez les utiliser pour écrire' instance's personnalisés. Par exemple, vous aurez du mal à écrire une instance de 'Monad' pour le' type C'. –

+0

Merci @BenjaminHodgson - Voulez-vous faire une réponse et je vais accepter? –

Répondre

3

Les différences sont les différences habituelles entre type et newtype. Un type synonyme est juste un nouveau nom pour un type existant. type Les synonymes ne peuvent pas être partiellement appliqués, car le compilateur développe la définition lors de la vérification de type. Par exemple, ce n'est pas bon, même avec 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) 

newtype s, alors que sur le plan opérationnel équivalent aux types qu'ils enveloppent, sont des entités distinctes dans le système de type. Cela signifie que newtypepeut être partiellement appliqué.

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)