
You are absolutely right about the tantalising opportunity. I know that Lennart has thought quite a bit about this very point when designing his Paradise system. Likewise Conal for Pan. One difficulty is, I think, that it's easy to get ambiguity. Eg ifthenelse (a > b) e1 e2 The (a>b) produces a boolean-thing, and ifthenelse consumes it; but which type of boolean? The Expr type? Real Bools? Or what? If there was a nice design, then GHC's existing -fno-implicit-prelude flag could be extended (again) to desugar if-then-else to the new thing. But the design is unclear, to me anyway. Simon | -----Original Message----- | From: haskell-cafe-bounces@haskell.org [mailto:haskell-cafe-bounces@haskell.org] On | Behalf Of Sebastiaan Visser | Sent: 27 May 2009 13:32 | To: Haskell Cafe | Subject: [Haskell-cafe] Bool as type class to serve EDSLs. | | Hello, | | While playing with embedded domain specific languages in Haskell I | discovered the Num type class is a really neat tool. Take this simple | example embedded language that can embed primitives from the output | language and can do function application. | | >data Expr :: * -> * where | > Prim :: String -> Expr a | > App :: Expr (a -> b) -> Expr a -> Expr b | | Take these two dummy types to represent things in the output language. | | >data MyNum | >data MyBool | | Now it is very easy to create an Num instance for this language: | | >primPlus :: Expr (MyNum -> MyNum -> MyNum) | >primPlus = Prim "prim+" | | >instance Num (Epxr MyNum) where | > a + b = primPlus `App` a `App` b | > fromInteger = Prim . show | > ... | | Which allows you to create very beautiful expression for your language | embedded inside Haskell. The Haskell expression `10 * 5 + 2' produces | a nice and well typed expression in your embedded domain. | | But unfortunately, not everyone in the Prelude is as tolerant as the | Num instance. Take the Eq and the Ord type classes for example, they | require you to deliver real Haskell `Bool's. This makes it impossible | make your DSL an instance of these two, because there are no `Bool's | only `Expr Bool's. | | Which brings me to the point that, for the sake of embedding other | languages, Haskell's Prelude (or an alternative) can greatly benefit | from (at least) a Boolean type class like this: | | class Boolean a where | ifthenelse :: a -> b -> b -> b -- Not sure about this | representation. | ... | | And one instance: | | >instance Boolean (Expr MyBool) where | > ifthenelse c a b = Prim "if-then-else" `App` c `App` a `App` b | | Now we can change (for example) the Eq type class to this: | | >class Eq a where | > (==) :: Boolean b => a -> a -> b | > (/=) :: Boolean b => a -> a -> b | | For which we can give an implementation for our domain: | | >primEq :: Epxr (a -> a -> MyBool) | >primEq = Prim "==" | | >instance Eq (Expr a) where | > a == b = primEq `App` a `App` b | | And now we get all functionality from the Prelude that is based on Eq | (like not, &&, ||, etc) for free in our domain specific language! Off | course there are many, many more examples of things from the standard | libraries that can be generalised in order to serve reuse in EDSLs. | | Anyone already working on such a generalized Prelude? I can imagine | much more domains can benefit from this than my example above. Any | interesting thoughts or pointers related to this subject? | | Gr, | | -- | Sebastiaan Visser | | _______________________________________________ | Haskell-Cafe mailing list | Haskell-Cafe@haskell.org | http://www.haskell.org/mailman/listinfo/haskell-cafe