SHARE
TWEET

Martin Pärtel

a guest Sep 30th, 2010 209 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. {-# LANGUAGE ExistentialQuantification #-}
  2.  
  3. -- This is taking a stab at mimicking the eff language in Haskell:
  4. -- http://math.andrej.com/2010/09/27/programming-with-effects-ii-introducing-eff/
  5.  
  6. -- A definition of an "operation" takes a continuation (y -> r)
  7. -- and gives a result a with it.
  8. data Def y r a = Def ((y -> r) -> a)
  9.  
  10. -- We make a monadic DSL for defining operations.
  11. instance Monad (Def y r) where
  12.   -- An operation just returning x can ignore its continuation.
  13.   return x = Def (\_ -> x)
  14.   -- An operation d followed by a choice of operation b means
  15.   -- d gets to look at the continuation k first and must return
  16.   -- something that is used to choose the appropriate b,
  17.   -- which gets to use the continuation next.
  18.   (Def d) >>= b' = Def (\k ->
  19.     let (Def b) = b' (d k)
  20.     in b k)
  21.  
  22. -- "yield y" is an operation yielding the given value y to the continuation
  23. -- and returning the result of the continuation directly.
  24. yield :: y -> Def y r r
  25. yield y = Def (\k -> k y)
  26.  
  27. -- Our "programs" can call the operations we've defined,
  28. -- or they can just return a constant.
  29. -- An operation invocation knows the op definition ((y -> r) -> a) and
  30. -- knows how to build the continuation program for a yielded value y.
  31. data Prog a = forall y r. ProgOp ((y -> r) -> a) (y -> Prog r)
  32.              | ProgRet a
  33.  
  34. -- We evaluate a call to an operation by giving the operation
  35. -- a continuation that, when yielded y, evaluates the continuation program
  36. -- chosen by y.
  37. evalProg :: Prog a -> a
  38. evalProg (ProgOp f k) = f (\y -> (evalProg (k y)))
  39. evalProg (ProgRet x) = x
  40.  
  41. -- Now we define the monadic DSL for defining programs that use the
  42. -- operations defined with the above.
  43. instance Monad Prog where
  44.   return x = ProgRet x
  45.   -- To sequence s and a choice of t, we do the following.
  46.   -- We define an operation that, given a continuation k goes to evaluate the
  47.   -- "first half" s and pass the result y to k.
  48.   -- We arrange k to be such that it uses the y to choose t.
  49.   s >>= t = ProgOp (\k -> k (evalProg s)) (\y -> t y)
  50.  
  51. -- A program consisting of just a call to an operation will just return the
  52. -- result the operation yields it.
  53. mkOp :: Def y y a -> Prog a
  54. mkOp (Def d) = ProgOp d (\y -> ProgRet y)
  55.  
  56.  
  57. -- Examples...
  58.  
  59. minChoose :: (Ord a) => a -> a -> Prog a
  60. minChoose a b = mkOp $
  61.   do l <- yield a
  62.      r <- yield b
  63.      return $ min l r
  64.  
  65. choiceExample =
  66.   do x <- choose 3 2
  67.      y <- choose 5 10
  68.      return $ x + y
  69.   where
  70.     choose = minChoose
  71.  
  72. -- yay! ^_^
  73.  
  74. -- Problem: mkOp would force a type equation () = (String, a)
  75. -- Well, they said they had problems coming up with a type system..
  76. --printToLog :: String -> Prog (String, a)
  77. printToLog msg = --mkOp $
  78.   do (log, result) <- yield ()
  79.      return (prepend msg log, result)
  80.   where
  81.     prepend msg "" = msg
  82.     prepend msg log = msg ++ ", " ++ log
  83.  
  84. main =
  85.   do print $ evalProg choiceExample
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top