在Haskell中有效匹配很多模式

时间:2013-05-21 00:15:03

标签: haskell pattern-matching packet

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

我的工作是:

  1. 收到数据包
  2. 将数据包标头解析为十六进制字符串(例如“02B5”)
  3. 从数据包中获取其余数据
  4. 在parseIO中匹配标头
  5. 使用数据包内容调用相应的函数
  6. 映射字符串很简单 - >方法,但方法有不同的参数量。

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

    #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. 在Map结构中存储(ByteString - > Function)。 O(log n)
    2. 将ByteString转换为Word16并进行模式匹配。 O(log n)到树或O(1)到查找表
    3. 编辑130521

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

      packetIO 0x02B5 = function1
      packetIO 0xADD5 = function2
      etc
      

2 个答案:

答案 0 :(得分:14)

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

答案 1 :(得分:10)

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

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

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