I have some difficulties to see the use of PromptT, because in the tutorial, this type is never mentioned, and its operations (Return and :&gt;&gt;=) are instead constructors of ProgramT...<br><br>Would you have some concrete examples? Because there I&#39;m a bit lost (since the tutorial doesn&#39;t match the operational package as it is, because of the type PromptT)...<br>
<br><div class="gmail_quote">2010/4/14 Heinrich Apfelmus <span dir="ltr">&lt;<a href="mailto:apfelmus@quantentunnel.de">apfelmus@quantentunnel.de</a>&gt;</span><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Bertram Felgenhauer wrote:<br>
<div class="im">&gt; Yves Parès wrote:<br>
&gt;&gt;<br>
&gt;&gt; I answered my own question by reading this monad-prompt example:<br>
&gt;&gt; <a href="http://paste.lisp.org/display/53766" target="_blank">http://paste.lisp.org/display/53766</a><br>
&gt;&gt;<br>
&gt;&gt; But one issue remains: those examples show how to make play EITHER a human<br>
&gt;&gt; or an AI. I don&#39;t see how to make a human player and an AI play SEQUENTIALLY<br>
&gt;&gt; (to a TicTacToe, for instance).<br>
&gt;<br>
&gt; A useful idea is to turn the construction upside-down - rather than<br>
&gt; implementing the game logic using MonadPrompt (or operational),<br>
&gt; implement the players in such a monad.<br>
&gt;<br>
&gt; A sketch:<br>
&gt;<br>
&gt;     {-# LANGUAGE GADTs, EmptyDataDecls #-}<br>
&gt;     import Control.Monad.Prompt hiding (Lift)<br>
&gt;<br>
&gt;     data Game -- game state<br>
&gt;     data Move -- move<br>
&gt;<br>
&gt;     data Request m a where<br>
&gt;         Board    :: Request m Game<br>
&gt;         MakeMove :: Move -&gt; Request m ()<br>
&gt;         Lift     :: m a -&gt; Request m a<br>
&gt;<br>
&gt;     type Player m a = Prompt (Request m) a<br>
<br>
</div>Just a small simplification: it is not necessary to implement the  Lift<br>
 constructor by hand, the  operational  library implements a generic<br>
monad transformer. The following will do:<br>
<br>
    import Control.Monad.Operational<br>
<br>
    data Request a where<br>
        Board    :: Request Game<br>
        MakeMove :: Move -&gt; Request ()<br>
<br>
    type Player m a = ProgramT Request m a<br>
<div class="im"><br>
    game :: Monad m =&gt; Player m () -&gt; Player m () -&gt; m ()<br>
</div>    game p1 p2 = do<br>
        g &lt;- initGame<br>
        eval&#39; g p1 p2<br>
        where<br>
        eval&#39; g p1 p2 = viewT p1 &gt;&gt;= \p1&#39; -&gt; eval g p1&#39; p2<br>
<br>
        eval :: Monad m =&gt; Game -&gt;<br>
           -&gt; Prompt Request m ()<br>
           -&gt; Player m ()<br>
           -&gt; m ()<br>
        eval g (Return _)            _  = return ()<br>
        eval g (Board       :&gt;&gt;= p1) p2 = eval&#39; g (p1 g) p2<br>
        eval g (MakeMove mv :&gt;&gt;= p1) p2 =<br>
            makeMove mv g &gt;&gt;= \g -&gt; eval&#39; g p2 (p1 ())<br>
<br>
This way, you are guaranteed not to break the lifting laws, too.<br>
<div class="im"><br>
&gt; What have we achieved? Both players still can only access functions from<br>
&gt; whatever monad m turns out to be. But now each strategy can pile its own<br>
&gt; custom monad stack on the  Player m  monad! And of course, the use of<br>
&gt; the m Monad is completely optional.<br>
<br>
</div>Of course, the custom monad stack has to provide a projection back to<br>
the  Player m a  type<br>
<br>
   runMyStackT :: MyStackT (Player m) a -&gt; Player m a<br>
<br>
Fortunately, you can&#39;t expect anything better anyway! After all, if the<br>
 game  function were to accept say  LogicT (Player m)  as well, this<br>
would mean that the player or AI could interleave the game arbitrarily,<br>
clearly not a good idea.<br>
<div class="im"><br>
&gt; Mapping between various &#39;m&#39; monads may also be useful:<br>
&gt;<br>
&gt;     mapPlayerM :: forall m1 m2 a . (forall a . m1 a -&gt; m2 a)<br>
&gt;                -&gt; Player m1 a -&gt; Player m2 a<br>
&gt;     mapPlayerM m1m2 pl = runPromptC return handle pl where<br>
&gt;         handle :: Request m1 x -&gt; (x -&gt; Player m2 a) -&gt; Player m2 a<br>
&gt;         handle (Lift a)      x = prompt (Lift (m1m2 a)) &gt;&gt;= x<br>
&gt;         handle (MakeMove mv) x = prompt (MakeMove mv) &gt;&gt;= x<br>
&gt;         handle (Board)       x = prompt (Board) &gt;&gt;= x<br>
&gt;<br>
&gt; This could be used to lock out the AI player from using IO, say.<br>
<br>
</div>Shouldn&#39;t this actually be a member of the  MonadTrans  class?<br>
<br>
    mapMonad :: (Monad m1, Monad m2, MonadTrans t) =&gt;<br>
        (forall a . m1 a -&gt; m2 a) -&gt; t m1 a -&gt; t m2 a<br>
<br>
?<br>
<br>
Regards,<br>
Heinrich Apfelmus<br>
<font color="#888888"><br>
--<br>
<a href="http://apfelmus.nfshost.com" target="_blank">http://apfelmus.nfshost.com</a><br>
</font><div><div></div><div class="h5"><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" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
</div></div></blockquote></div><br>