Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Match a lot of patterns in Haskell efficiently

I have thought of using Haskell for a game server but when coding, I found myself looking at the part where I parse packets thinking "wow, this will result in a lot of pattern matching". This seeing the amount of matches to be done are many (walk there, attack that, loot that, open that, and so on).

What I do is:

  1. Receive a packet
  2. Parse the packet header into a hexadecimal String (say "02B5" for example)
  3. Get rest of data from the packet
  4. Match header in parseIO
  5. Call the appropriate function with the packet content

It would be easy to map String -> method, but the methods have different amount of in-parameters.

I thought of the simple two ways of pattern matching shown below.

#1
packetIO :: String -> IO ()
packetIO packet =
  case packet of
    "02B5" -> function1
    "ADD5" -> function2
    ... and so on

#2
packetIO :: String -> IO ()
packetIO "02B5" = function1
packetIO "ADD5" = function2
... and so on

Both looking at performance and coding style, is there a way to better handle the packets received from the client?

If you have any resources or links I failed to find, please do point me in their direction!

EDIT 130521:

Seems like both alternatives, listed below, are good choices. Just waiting to see answers to my questions in the comments before choosing which was the best solution for me.

  1. Storing (ByteString -> Function) in a Map structure. O(log n)
  2. Converting ByteString to Word16 and pattern match. O(log n) through tree or O(1) through lookup tables

EDIT 130521:

Decided to go for pattern matching with Word16 as Philip JF said. Both are great alternatives and while my guess is both is equally fast, Map might be faster seeing I don't have to convert to Word16, the other option gave more readable code for my use:

packetIO 0x02B5 = function1
packetIO 0xADD5 = function2
etc
like image 348
Plankt Avatar asked May 21 '13 00:05

Plankt


1 Answers

Why not parse to numbers (Word16 in Data.Word?) and then do the matching with that, instead of using strings? Haskell supports hex literals...

like image 150
Philip JF Avatar answered Nov 10 '22 09:11

Philip JF