<div dir="ltr"><br><br>On Friday, March 14, 2014 5:19:40 PM UTC-4, Eric Walkingshaw wrote:<blockquote class="gmail_quote" style="margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir="ltr"><div><div>I'm not sure if this answers your questions, but I think this particular problem has a cleaner solution with GADTs:</div><div><br></div><div>    {-# LANGUAGE GADTs #-}</div>

<div>    </div><div>    data Cmd s t where</div><div>      Push :: a             -> Cmd s         (a,s)</div><div>      F1   :: (a -> b)      -> Cmd (a,s)     (b,s)</div><div>      F2   :: (a -> b -> c) -> Cmd (a,(b,s)) (c,s)</div>

<div>    </div><div>    data Prog s t where</div><div>      (:.) :: Cmd s t -> Prog t u -> Prog s u</div><div>      End  :: Prog s s</div><div>    </div><div>    infixr 5 :.</div><div>    </div><div>    cmd :: Cmd s t -> s -> t</div>

<div>    cmd (Push a) s         = (a, s)</div><div>    cmd (F1 f)   (a,s)     = (f a, s)</div><div>    cmd (F2 f)   (a,(b,s)) = (f a b, s)</div><div>    </div><div>    prog :: Prog s t -> s -> t</div><div>    prog (c :. p) s = prog p (cmd c s)</div>

<div>    prog End      s = s</div><div>    </div><div>    run :: Prog () t -> t</div><div>    run p = prog p ()</div><div><br></div><div>Then from GHCi:</div><div>    </div><div>    > run (Push 3 :. Push 4 :. F2 (+) :. F1 show :. End)</div>

<div>    ("7",())</div><div><br></div><div>Maybe you really want GADTs? :)</div><div><br></div><div>-Eric</div></div></div></blockquote><div><br>That's a great point, thanks. I'll have to remember to interrogate myself on that next time I find myself reaching for this pattern. I wonder if your version can be made to work for functions of any arity?<br><br>But in most (maybe not all) cases I really don't want to be defining new types.<br><br>Thanks,<br>Brandon<br></div></div>