<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>