6

我曾想过将 Haskell 用于游戏服务器,但在编码时,我发现自己在查看解析数据包的部分时会想“哇,这将导致很多模式匹配”。这看到要完成的匹配数量很多(走到那里,攻击那个,掠夺那个,打开那个,等等)。

我要做的是:

  1. 接收数据包
  2. 将数据包头解析为十六进制字符串(例如“02B5”)
  3. 从数据包中获取其余数据
  4. parseIO 中的匹配标头
  5. 使用数据包内容调用相应的函数

映射 String -> 方法很容易,但是这些方法的参数数量不同。

我想到了下面显示的两种简单的模式匹配方式。

#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

从性能和编码风格来看,有没有办法更好地处理从客户端收到的数据包?

如果您有任何我找不到的资源或链接,请指出我的方向!

编辑 130521

似乎下面列出的两种替代方案都是不错的选择。只是等待在评论中看到我的问题的答案,然后再选择最适合我的解决方案。

  1. 将 (ByteString -> Function) 存储在 Map 结构中。O(log n)
  2. 将 ByteString 转换为 Word16 和模式匹配。O(log n) 通过树或 O(1) 通过查找表

编辑 130521

正如 Philip JF 所说,决定使用 Word16 进行模式匹配。两者都是很好的选择,虽然我的猜测是同样快,但 Map 可能会更快,因为我不必转换为 Word16,另一个选项为我的使用提供了更具可读性的代码:

packetIO 0x02B5 = function1
packetIO 0xADD5 = function2
etc
4

2 回答 2

14

为什么不解析为数字Word16in Data.Word?)然后与之匹配,而不是使用字符串?Haskell 支持十六进制文字...

于 2013-05-21T02:22:22.967 回答
10

Both of your functions are equivalent. The compiler desugars the second one to the first one. Pattern matching is syntactic sugar for case.

case is optimal for this kind of thing. It compiles to a jump table, which is O(1). That means both of the solutions you listed are optimal.

As far as coding style goes, both styles are perfectly idiomatic. I personally prefer case over pattern matching, but I know a lot of other people prefer pattern matching for top-level functions.

于 2013-05-21T00:18:22.357 回答