On Mon, Jul 13, 2009 at 6:09 AM, Chris Eidhof <span dir="ltr">&lt;<a href="mailto:chris@eidhof.nl">chris@eidhof.nl</a>&gt;</span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Hey Kev,<br>
<br>
The types are &quot;thrown away&quot; during compile time. Therefore, if you have a constructor &quot;VWrapper :: a -&gt; Value&quot; nothing is known about that &quot;a&quot; when you scrutinize it.<br>
<br>
What you could do, however, is something like this:<br>
<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
data Value a where<br>
  VInt :: Integer -&gt; Value Integer<br>
  ...<br>
  VWrapper :: a -&gt; Value a<br>
</blockquote>
<br>
And then you can write a function doSomething:<br>
<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
doSomething :: Value String -&gt; String<br>
doSomething (VWrapper s) = s</blockquote></blockquote><div><br>I would like to put in a thumbs up on this approach.  I&#39;m currently experimenting with interpreters, and have found that parameterizing over the value type works quite smoothly.<br>
<br>Specifically, this is my usual starting point for the values:<br><br>    data Value a<br>        = VFun (Value a -&gt; Value a)<br>        | VPrim a<br><br>Then I use a typeclass to endow the primitives with the structure they need:<br>
<br>    class ValueType a where<br>        apply :: a -&gt; a -&gt; a<br><br>Here&#39;s a simple interpreter for terms in De Bruijn notation:<br><br>    data Term a<br>        = TLit a<br>        | TApp (Term a) (Term a)<br>
        | TLam (Term a)<br>        | TVar Int<br><br>    eval :: (ValueType a) =&gt; Term a -&gt; [Value a] -&gt; Value a<br>    eval (TLit x) = const (VPrim x)<br>    eval (TApp x y) = <br>        let x&#39; = eval x<br>
            y&#39; = eval y<br>        in \env -&gt; x&#39; env % y&#39; env<br>    eval (TLam body) = <br>        let body&#39; = eval body<br>        in \env -&gt; VFun (\x -&gt; body (x:env))<br>    eval (TVar z) = \env -&gt; env !! z<br>
<br>    (%) :: (ValueType a) =&gt; Value a -&gt; Value a -&gt; Value a<br>    VFun f % x = f x<br>    VPrim x % VFun _ = error &quot;Apply primitive to function not supported&quot;<br>    VPrim x % VPrim y = VLit (x `apply` y)<br>
<br>And an example ValueType:<br><br>    data Prim = PInt Int | PSucc<br>    instance ValueType Prim where<br>        apply PSucc (PInt z) = PInt $! z+1<br>        apply _ _ = error &quot;Type error&quot;<br><br>This approach has been very nice and modular for experimenting with dynamically typed interpreters. You could support application of literals to functions with some more support from the type class, but it wasn&#39;t worth it to me (and would limit the interpretation strategies that I would be able to use).<br>
<br>The decision about what suite of primitives to include and how they combine with each other is pushed out to the user, and the interpreter just focuses on the important things: functions.  You could even write a little primitive combinator library (perhaps made more composable by switching to dictionary passing for ValueType instead of typeclass), so that users can easily specify any suite of primitives.<br>
<br>Anyway, those were just some thoughts for you.<br><br>Luke</div></div>