I have not compiled the program so be ware of errors.

`pipeScore` currently loops when you call `go` and also after the yield in
the section:

                            if isGameOver b'
                                then yield (Left "Game over. Bye. See you
next time")
                                else go b'

from the use of `for cat`

I would suggest only looping with one mechanism.

Something like:
pipeScore =  go
    where
        go b =  do
            x <- await
            case x of
                Left s -> yield (Left s)
                Right n -> do
                    case score n b of
                        Right (a', b') -> do
                            yield (Right (a',b'))
                            if isGameOver b'
                                then do
                                  yield (Left "Game over. Bye. See you next
time")
                                  go b
                                else go b'
                        Left msg -> do
                            yield (Left msg)
                            go b

The second thing that I noticed was that you are not modifying the the
upstream left value or the right left value.


You should look at the pipes-extras `left` and `right` functions on pipes.

You isolate the game board functionality from handling either the left or
the right left value, and isolate the game over functionality.

-- You ignore lefts so you do not need to right a pipe to handle them.
right (right pipeScore' >-> pipeIsGameOver)

-- You can isolate the board state to a tighter pipe if you want to
separate out
-- functionality
pipeScore' = go
  where
    go b = do
      n <- await
      let (a', b') = score n b
      yield (a', b')
      go b'

pipeIsGameOver = do
  where
    go = do
      ex <- await
      case ex of
        Right (a, b) -> do
          if isGameOver b
          then do
            yield (Left "Game over. Bye. See you next time")
            go
          else go
        Left msg -> do
          yield msg
          go

The right and left sections of pipeIsGame Over could be broken apart as
well, however those combinators are not in a library that I know of.

They would be translation of the old bindPull operator from pipes-parse-1.0
http://hackage.haskell.org/package/pipes-parse-1.0.0/docs/Control-Proxy-Parse.html#v:bindPull

If you made those combinators then you could write something like

right (right pipeScore' >-> bindPullRight pipeIsGameOver)


pipeIsGameOver' = do
  where
    go = do
      (a, b) <- await
        if isGameOver b
        then do
          yield (Left "Game over. Bye. See you next time")
          go
        else go

The MVC library does seem to set up to make some of these types of
operation a little more automatic as well as more type safe.  I have not
played around with it much yet though so I would not know how to do a
bindPullRight like behavior with it.

I have not benchmarked `right`, `left`, `bindPull` vs handling everything
with explicit case statements.  I do think it is much easier to break a
problem down into subproblems with them though.

Patrick


On Sun, May 11, 2014 at 4:58 AM, Pierre R <[email protected]> wrote:

> In the
>
>
> On Saturday, May 10, 2014 2:01:04 AM UTC+2, Gabriel Gonzalez wrote:
>>
>>  Sorry for the late response, but I was busy preparing for BayHac.
>>
>> I really loved Tony's `mvc`-based solution (of course I'm biased).  The
>> only thing I wanted to add was the following rule of thumb for how to get
>> local vs global state.
>>
>> For local state, put the `StateT` layer outside the `Pipe` layer and then
>> immediately run the `StateT` layer before composing it with other pipes:
>>
>>     numbers :: Monad m => Producer Int m r
>>     numbers = flip evalStateT 0 $ forever $ do
>>         n <- get
>>         lift (yield n)
>>         put $! n + 1
>>
>
> For local state,  I guess a loop might be as good, isn't ?
> numbers :: Monad m => Int -> Producer Int m r
> numbers = go
>     where
>         go n = do yield n; go $! n + 1
>
> `PipeScore` for instance seems to be better expressed as such:
> pipeScore :: (Monad m) => Board -> Pipe (Either String Int) (Either String
> (Int,Board)) m ()
> pipeScore =  go
>     where
>         go b =  do
>             for cat $ \x -> case x of
>                 Left s -> yield (Left s)
>                 Right n -> do
>                     case score n b of
>                         Right (a', b') -> do
>                             yield (Right (a',b'))
>                             if isGameOver b'
>                                 then yield (Left "Game over. Bye. See you
> next time")
>                                 else go b'
>                         Left msg -> do
>                             yield (Left msg)
>                             go b
>
> --
> You received this message because you are subscribed to the Google Groups
> "Haskell Pipes" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To post to this group, send email to [email protected].
>



-- 
Patrick Wheeler
[email protected]
[email protected]
[email protected]

-- 
You received this message because you are subscribed to the Google Groups 
"Haskell Pipes" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].

Reply via email to