Hi Daniil,<br><br>By &quot;embedded&quot; DSL, we usually mean identifying meta-language (Haskell)
expressions with object language (DSL) expressions, rather than having
an &quot;Exp&quot; data type.&nbsp; Then you just use meta-language variables as
object-language variables.&nbsp; The new data types you introduce are then
domain-oriented rather than language-oriented.&nbsp; Is there a reason that
this kind of &quot;embedded&quot; approach doesn&#39;t work for you?<br>
<br>
Cheers,&nbsp; - Conal<br><br><div><span class="gmail_quote">On 6/7/07, <b class="gmail_sendername">Daniil Elovkov</b> &lt;<a href="mailto:daniil.elovkov@googlemail.com">daniil.elovkov@googlemail.com</a>&gt; wrote:</span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Hello folks<br><br>Haskell is considered good for embedded DSLs. I&#39;m trying to implement<br>some simple EDSL in a typeful manner and having a problem with looking<br>up variable values.<br><br>I&#39;ve got an Expression GADT, which admits variables. The problem is
<br>with writing compute function which will lookup variable values in a<br>type-safe manner.<br><br>The exp. data type is like this<br><br>data Exp a where<br>&nbsp;&nbsp; Const a :: Val a -&gt; Exp a<br>&nbsp;&nbsp; Var :: a -&gt; String -&gt; Exp a -- where the first comp. isn&#39;t
<br>used,only for type info.<br>&nbsp;&nbsp; ....<br><br>So, obviously, I have to perform lookups in some &#39;scope&#39; to compute<br>the expression. By scope I mean the list of (name,value) pairs.<br><br>How do I represent the scope? Well, I haven&#39;t gone that far as to
<br>encode statically the information about the type of every variable in<br>scope. Instead, I used existentials to hide their types and put&#39;em all<br>in a list.<br><br>For that purpose I introduced pack/unpack.<br><br>
-- value with dynamic type annotation<br>-- m here and below can be Val, Exp, etc.<br>--&nbsp;&nbsp;&nbsp;&nbsp; to represent Val Int, Exp Int, etc.<br>data Type m = TInt (m Int)&nbsp;&nbsp;| TString (m String) | TDouble (m Double)<br><br>class Typed a where
<br>&nbsp;&nbsp;&nbsp;&nbsp;typ&nbsp;&nbsp; :: m a -&gt; Type m<br><br>instance Typed Int where typ x = TInt x<br>instance Typed String where typ x = TString x<br>instance Typed Double where typ x = TDouble x<br><br>data Opaque m = forall a. (Typed a) =&gt; Opaque (m a)
<br><br>-- extract to an annotated representation<br>extract :: Opaque m -&gt; Type m<br>extract (Opaque a) = typ a<br><br>How would you suggest, I write compute function?<br><br>My try was<br><br>compute :: Scope -&gt; Exp t -&gt; Val t
<br>compute scope (Const x) = x -- trivial<br><br>compute scope (Var t name) = -- intereseting part<br>&nbsp;&nbsp;&nbsp;&nbsp;let opq = lookup name scope<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;val = case opq of<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Nothing&nbsp;&nbsp;-&gt; error &quot;not in scope&quot;
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Just opq -&gt; extract opq<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;expType&nbsp;&nbsp; = aux t<br>&nbsp;&nbsp;&nbsp;&nbsp;in case val `matches` expType of -- I&#39;d like to make some &#39;matches&#39; func.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Nothing -&gt; error &quot;type error&quot; -- which would either produce an error
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Just v&nbsp;&nbsp;-&gt; v&nbsp;&nbsp;&nbsp;&nbsp; -- or return the value, based on run-time tags<br><br>matches :: Typed m -&gt; Typed m -&gt; Maybe (m a)<br>&nbsp;&nbsp;BUT of course this type is bad, there&#39;s no &#39;a&#39; in the left side<br>
matches (TInt x) (TInt _) = Just x<br>matches (TString x) (TString _) = Just x<br>matches (TDouble x) (TDouble _) = Just x<br>matches _ _&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = Nothing<br><br>So, clearly the problem is in that Type m has no evidence of a, which
<br>was its very purpose. Ok, so I made<br><br>data FType m a where<br>&nbsp;&nbsp;&nbsp;&nbsp;FInt :: m Int -&gt; FType m Int<br>&nbsp;&nbsp;&nbsp;&nbsp;FString :: m String -&gt; FType m String<br>&nbsp;&nbsp;&nbsp;&nbsp;FDouble :: m Double -&gt; Aux m a<br><br>class Typed a where
<br>&nbsp;&nbsp;&nbsp;&nbsp;typ&nbsp;&nbsp; :: m a -&gt; Type m -- as before<br>&nbsp;&nbsp;&nbsp;&nbsp;ftyp :: m a -&gt; FType m a -- new one<br><br>and again obvious instance<br>instance Typed Int where ftyp x = FInt x<br>...<br><br>And of course, I&#39;d like to get that information somehow
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; extract2 (Opaque a) = ftyp a<br>I rewrote &#39;matches&#39; accordingly but the problem is already in the type<br>of extract2<br><br>its type Opaque m -&gt; (forall a. (Typed a) =&gt; m a)<br>is not good to ghc, less polymorphic than expected
<br><br>So, in principle it must be doable, since opaque data retains its<br>dictionary, and by that I can get a dynamic tag, say FInt x, where x<br>is proved to be Int.<br><br>What would you suggest?<br><br>Thank you<br>
_______________________________________________<br>Haskell-Cafe mailing list<br><a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br><a href="http://www.haskell.org/mailman/listinfo/haskell-cafe">http://www.haskell.org/mailman/listinfo/haskell-cafe
</a><br></blockquote></div><br>