Very little (golfing) question...

Hi, I always write functions like this: addPlayer :: PlayerInfo -> State Game Bool addPlayer pi@(PlayerInfo {playerNumber = pn}) = do pls <- gets players case find (\(PlayerInfo {playerNumber = myPn}) -> pn == myPn) pls of Nothing -> do modify (\game -> game { players = pi : pls}) return True otherwise -> return False It simply adds a new PlayerInfo to a list contained in Game, with the condition that it doesn't exists already. Do you see a more elegant way to do this? Best, Corentin

This is marginally clearer, but not all that great.
import Data.List as L
import Control.Monad.State
import Data.Maybe (isJust)
data PlayerInfo = PlayerInfo {
playerNumber :: Integer
}
instance Eq PlayerInfo where
p1 == p2 = playerNumber p1 == playerNumber p2
data Game = Game {
players :: [PlayerInfo]
}
addPlayer newPlayer = do
exists <- fmap (isJust . find (==newPlayer)) $ gets players
when exists $ gets players >>= \oldPlayers -> modify (\game -> game
{ players = newPlayer:oldPlayers })
return exists
So, add an Eq instance to players so that you can just compare them
simply without deconstructing them all the time.
However, if you were to give an Ord instance to players, you could
replace lists with sets, which will allow you to insert without caring
whether the player is already in the set. If you are dead set on
getting back a boolean, then you'll still have to check for existence
with member, so you won't gain much in brevity. But if you weren't,
you could shorten it considerably to:
import Control.Monad.State
import Data.Set as S
data PlayerInfo = PlayerInfo {
playerNumber :: Integer
} deriving Ord
instance Eq PlayerInfo where
p1 == p2 = playerNumber p1 == playerNumber p2
data Game = Game {
players :: Set PlayerInfo
}
addPlayer newPlayer = modify $
\game@(Game { players = oldPlayers }) -> game { players = S.insert
newPlayer oldPlayers }
On Wed, Jul 25, 2012 at 5:02 PM, Corentin Dupont
Hi, I always write functions like this:
addPlayer :: PlayerInfo -> State Game Bool addPlayer pi@(PlayerInfo {playerNumber = pn}) = do pls <- gets players case find (\(PlayerInfo {playerNumber = myPn}) -> pn == myPn) pls of Nothing -> do modify (\game -> game { players = pi : pls}) return True otherwise -> return False
It simply adds a new PlayerInfo to a list contained in Game, with the condition that it doesn't exists already. Do you see a more elegant way to do this?
Best, Corentin
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

On Wed, Jul 25, 2012 at 11:02:39PM +0200, Corentin Dupont wrote:
This is a little better, it avoids all the record syntax for extracting player numbers, and uses 'any' instead of 'find' since we don't actually care about the player with the given number if they exist:
addPlayer :: PlayerInfo -> State Game Bool addPlayer pi = do pls <- gets players let exists = any (((==) `on` playerNumber) pi) pls when (not exists) $ modify (\game -> game { players = pi : pls}) return $ not exists
-Brent

Thanks Brent and David, that's very neat!
I always forget to use these operators 'on', 'when', 'any'...
I also always hesitate on the container to use, list, sets or something
else... Now everything is done with lists since they are very well
supported by the prelude...
On Thu, Jul 26, 2012 at 2:31 AM, Brent Yorgey
On Wed, Jul 25, 2012 at 11:02:39PM +0200, Corentin Dupont wrote:
This is a little better, it avoids all the record syntax for extracting player numbers, and uses 'any' instead of 'find' since we don't actually care about the player with the given number if they exist:
addPlayer :: PlayerInfo -> State Game Bool addPlayer pi = do pls <- gets players let exists = any (((==) `on` playerNumber) pi) pls when (not exists) $ modify (\game -> game { players = pi : pls}) return $ not exists
-Brent
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
participants (3)
-
Brent Yorgey
-
Corentin Dupont
-
David McBride