
Hi everyone, Well, I'm trying to build a soccer server client and am using Haskell. I thought I was muddling through well enough... but I have some questions. I am using the Robot monad that I copied from Hudak's book HSOE from page 272 (assuming I would understand it later). Here's the monad code I copied: newtype Robot a = Robot (RobotState -> IO (RobotState, a)) instance Monad Robot where return a = Robot (\s -> return (s, a)) Robot sf0 >>= f = Robot (\s0 -> do (s1, a1) <- sf0 s0 let Robot sf1 = f a1 (s2, a2) <- sf1 s1 return (s2, a2)) updateState :: (RobotState -> RobotState) -> Robot () updateState u = Robot (\s -> return (u s, ())) queryState :: (RobotState -> a) -> Robot a queryState q = Robot (\s -> return (s, q s)) I defined myself a comfortable "chunk of state" (comfortable for today at least): data RobotState = RobotState { player_type :: RobotType, team_name :: String, my_current_position :: Position, visible_flags :: [ObjInfo], visible_ball :: [ObjInfo], visible_friends :: [ObjInfo], visible_foes :: [ObjInfo], audible_player_messages :: [String], my_current_mode :: RobotMode, debug_level :: [RobotDebugLevel], my_uniform_number :: Integer, game_mode :: GameMode, game_clock :: Integer } deriving Show In addition, I added some support functions similar to the ones he wrote in Section 19.3.1: assign_flags :: [ObjInfo] -> Robot () assign_flags flaglist = updateState (\s -> s {visible_flags = flaglist}) assign_friends :: [ObjInfo] -> Robot () assign_friends friendlist = updateState (\s -> s {visible_friends = friendlist}) assign_foes :: [ObjInfo] -> Robot () assign_foes foelist = updateState (\s -> s {visible_foes = foelist}) assign_ball :: [ObjInfo] -> Robot () assign_ball balllist = updateState (\s -> s {visible_ball= balllist}) Now, I read several online monad tutorials and kind of understand the notion of a thread of function calls. And I know that the do notation is syntactic sugar for the bind operation. But the code I've written is really nasty. For example, here is part of my code that handles a see record and returns a new RobotState: handleSeeRecord :: [SeeObjInfo_type] -> RobotState -> IO (RobotState, ()) handleSeeRecord seeobjlist p = do flaglist <- return (morphToList flagFinder seeobjlist) balllist <- return (morphToList ballFinder seeobjlist) friendlist <- return (morphToList friendFinder seeobjlist) foelist <- return (morphToList foeFinder seeobjlist) Robot e <- return (assign_flags (flagSpread flaglist)) Robot f <- return (assign_ball balllist) Robot g <- return (assign_friends friendlist) Robot h <- return (assign_foes foelist) (r', ()) <- e p (r'', ()) <- f r' (r''', ()) <- g r'' h r''' This actually works, but I think it can be improved with the bind operation >>= somehow. I tried a few alternatives but couldn't find one that worked. I ended up with this because it seems I had to "strip" the type off of "return (assign_flags (flagSpread flaglist))" and get the "e" that was a function. Might someone have a suggestion on how to improve this? thanks -andrew

On 2004 September 19 Sunday 13:40, Andrew Harris wrote:
handleSeeRecord :: [SeeObjInfo_type] -> RobotState -> IO (RobotState, ()) handleSeeRecord seeobjlist p = do flaglist <- return (morphToList flagFinder seeobjlist) balllist <- return (morphToList ballFinder seeobjlist) friendlist <- return (morphToList friendFinder seeobjlist) foelist <- return (morphToList foeFinder seeobjlist) Robot e <- return (assign_flags (flagSpread flaglist)) Robot f <- return (assign_ball balllist) Robot g <- return (assign_friends friendlist) Robot h <- return (assign_foes foelist) (r', ()) <- e p (r'', ()) <- f r' (r''', ()) <- g r'' h r'''
What you're looking for is something like handleSeeRecord :: [SeeObjInfo_type] -> Robot () handleSeeRecord seeobjlist = do let flaglist = morphToList flagFinder seeobjlist let balllist = morphToList ballFinder seeobjlist let friendlist = morphToList friendFinder seeobjlist let foelist = morphToList foeFinder seeobjlist assign_flags (flagSpread flaglist) assign_ball balllist assign_friends friendlist assign_foes foelist This uses the 'do' notation with the Robot monad, whose operations are closer to what the code is doing than the IO monad. Also, replacing 'return' with 'let' removes the unnecessary reference to the monad.
participants (2)
-
Andrew Harris
-
Scott Turner