
On Wed, Jul 29, 2009 at 09:19:39AM +0900, Yang, Chul-Woong wrote:
data Packet = Packet { foo :: Word16, bar :: Word16, baz :: Word32 } deriving (Show, Eq)
instance Binary Packet where get = do foo <- get :: Get Word16 bar <- get :: Get Word16 baz <- get :: Get Word32 return (Packet foo bar baz) -- omitting put because we're now just receiving only
By the way, I have nothing to contribute towards solving your actual problem, but I wanted to point out that you can write this Binary instance much more simply. First of all, you can just write
instance Binary Packet where get = do foo <- get bar <- get baz <- get return (Packet foo bar baz)
and through the magic of type inference, Haskell will figure out the right instances to use based on the fact that you use foo, bar, and baz as arguments to Packet, which expects certain types. (Although having the type signatures there as documentation is not a terrible idea.) But actually, we can do even better:
import Control.Applicative
instance Binary Packet where get = Packet <$> get <*> get <*> get
Amazing! =) This is exactly the sort of thing Applicative is for. It lets us program in an "applicative" style where we apply functions to arguments, where the arguments are computed in some sort of context that may have "effects". Monads give us the power to decide which monadic actions to run next based on the results of a previous action, but we don't need that power here: we are always going to run 'get' three times and put the results in a Packet. Using Applicative lets us avoid giving names to the results of the calls to get. -Brent