{-# LANGUAGE GADTs #-} {-| A simple embedded language for input/output. Deep embedding. -} module Program.Deep1 where type Input = String type Output = String -- | The trivial deep embedding. We need to use a GADT to be allowed -- the specific types on 'Get' and 'Put'. data Program a where Put :: Char -> Program () Get :: Program (Maybe Char) Return :: a -> Program a (:>>=) :: Program a -> (a -> Program b) -> Program b -- | run function: translate syntax to semantics (Meaning as builtin Haskell) run :: Program a -> Input -> (a, Input, Output) run (Put c) i = ((), i, [c]) run Get [] = (Nothing, [], []) run Get (c : i) = (Just c, i, []) run (Return x) i = (x, i, []) run (p :>>= f) i = let (x, i1, o1) = run p i (y, i2, o2) = run (f x) i1 in (y, i2, o1 ++ o2) instance Monad Program where return = Return (>>=) = (:>>=) -- | Output a character. putC :: Char -> Program () putC = Put -- | Input a character. getC :: Program (Maybe Char) getC = Get