<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><div>Type families can be used to great effect in this area. &nbsp;For instance, in Potential (<a href="http://potential-lang.org">http://potential-lang.org</a>) we use two tricks for making sure that the combinators in our EDSL are are obeying our rules for composition:</div><div><br></div><div>(a) We use type families as type-level functions for describing how state transforms, and</div><div>(b) We use a custom Monad class whose &gt;&gt; and &gt;&gt;= use our type families. &nbsp;(This is only so that we can use 'do' notation; we could let go of 'do' notation and leave the Monad class alone).</div><div><br></div><div>We use this combo in many different ways. &nbsp;For instance, in our EDSL we have certain combinators which&nbsp;<i>cannot</i>&nbsp;be followed by any other combinators (we say they are "terminal"). We have others which&nbsp;<i>can</i>&nbsp;be followed by others (we say they are "composable"). &nbsp;We also have a weird class of operations which don't really interact with our state and are thus able to break the rules (we say they are "unmodeled"; we only use this designation for data plumbing, like `return,' which is why it's allowed to break the rules).</div><div><br></div><div>We then have a type family</div><div><br></div><div>class ComposeC a b where type ComposeT a b</div><div><br></div><div>and instances like</div><div><br></div><div><div>instance CombposeC Terminal Unmodeled where</div><div>&nbsp;&nbsp;type ComposeT Terminal Unmodeled = Terminal</div></div><div><br></div><div>instance CombposeC Composable Terminal where</div><div>&nbsp;&nbsp;type ComposeT Composable Terminal = Terminal</div><div><br></div><div><div>instance CombposeC Composable Unmodeled where</div><div>&nbsp;&nbsp;type ComposeT Composable&nbsp;Unmodeled&nbsp;= Composable</div></div><div><br></div><div><div><div>instance CombposeC Unmodeled&nbsp;Composable&nbsp;where</div><div>&nbsp;&nbsp;type ComposeT Unmodeled&nbsp;Composable&nbsp;= Composable</div></div></div><div><br></div><div><div>instance CombposeC Composable Composable where</div><div>&nbsp;&nbsp;type ComposeT Composable Composable = Composable</div></div><div><br></div><div><div>instance CombposeC&nbsp;Unmodeled&nbsp;Unmodeled where</div><div>&nbsp;&nbsp;type ComposeT&nbsp;Unmodeled&nbsp;Unmodeled&nbsp;=&nbsp;Unmodeled</div></div><div><br></div><div>Our &gt;&gt;= operator now looks like</div><div><br></div><div>(&gt;&gt;=) :: (ComposeC ct ct') =&gt; m ct a -&gt; (a -&gt; m ct' b) -&gt; m (Compose ct ct') b</div></div><div><br></div><div><br></div><div>There is a practical side-effect, unfortunately, which is that type-level computation in Haskell can be cumbersome (type families are lazily evaluated in GHC) and lead to hard-to-read errors (errors often manifest as "No instance for...").</div><div><br></div><br><div><div>On Sep 17, 2010, at 11:27 AM, Günther Schmidt wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div>Hello,<br><br>I'd want to create a EDSL where I want to be able to statically ensure <br>that expressions can only be built according to a particular "state".<br><br>Like in a network application, SMTP client for example, where I can only <br>issue commands if the application is in a certain state.<br><br>Are there any Haskell examples for this sort of thing?<br><br>Günther<br><br>_______________________________________________<br>Haskell-Cafe mailing list<br><a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>http://www.haskell.org/mailman/listinfo/haskell-cafe<br></div></blockquote></div><br></body></html>