在Haskell中有效匹配很多模式

Pla*_*nkt 6 haskell pattern-matching packet

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

我所做的是:

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

映射String - > method会很容易,但是这些方法具有不同的in-parameters数量.

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

#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
Run Code Online (Sandbox Code Playgroud)

两者都在考虑性能和编码风格,有没有办法更好地处理从客户端收到的数据包?

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

编辑130521:

看起来像下面列出的两种选择都是不错的选择.只是等待在评论中看到我的问题的答案,然后选择哪个是我的最佳解决方案.

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

编辑130521:

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

packetIO 0x02B5 = function1
packetIO 0xADD5 = function2
etc
Run Code Online (Sandbox Code Playgroud)

Phi*_* JF 14

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


Gab*_*lez 10

你的两个功能都是等价的.编译器将第二个去掉第一个.模式匹配是语法糖case.

case对于这种事情是最佳的.它编译为跳转表,即O(1).这意味着您列出的两种解决方案都是最佳的.

就编码风格而言,两种风格都是完全惯用的.我个人更喜欢case模式匹配,但我知道很多其他人更喜欢顶级功能的模式匹配.

  • 是否也使用`String`s编译到跳转表?我对此表示怀疑. (4认同)