用于数据类型字段提取的模式匹配与记录语法功能

时间:2012-04-24 03:56:43

标签: haskell

给出具有记录语法的示例数据类型:

data VmInfo = VmInfo {infoVid   :: String
                     ,infoIndex :: Int
                     ,infoPid   :: Int
                     ,infoExe   :: String
                     } deriving (Show)

和(vmInfo :: String - > VmInfo)函数,它生成并返回上面给定vm名称为字符串的数据结构。

我可以看到两种方法来提取VmInfo数据类型的各个部分。

(VmInfo vid _ _ _) <- vmInfo vm

这只是模式匹配。而且......

vid <- infoVid <$> vmInfo vm

使用记录语法编译器生成的函数。

问题很简单:哪种方法更受欢迎?

打字量明智,他们是相同的,所以我正在寻找速度和正确/最佳实践。

我认为模式匹配会更快,但记录语法的重点是什么?

感谢。

1 个答案:

答案 0 :(得分:8)

这些在语义上不等同。

让我们看看第一个例子:

(VmInfo vid _ _ _) <- vmInfo vm

这在绑定操作中执行模式匹配。有两个结果。第一个是评估vmInfo vm动作结果的构造函数。这意味着,如果vmInforeturn undefined之类的行结尾,则评估undefined时引发的异常将在此模式匹配时发生,而不是稍后使用vid。第二个是如果模式匹配被反驳(模式匹配与值不匹配),将使用模式匹配错误文本调用monad的fail实例。在这种情况下,这是不可能的,但通常可以在模式匹配绑定中的构造函数时使用。

现在,转到下一个例子:

vid <- infoVid <$> vmInfo vm

根据<$>的定义,这将在动作返回的值(而不是效果)中完全是懒惰的。如果vmInforeturn undefined结尾,则在您使用undefined的值执行操作之前,您不会从评估vid获得异常。此外,如果infoVoid能够抛出任何异常,那么在使用vid之前最终不会发生这种情况,最好的情况。

有趣的是,这些差异仅出现在monadic绑定的范围内。如果vmInfo是纯粹的,并且您在vidlet表达式中绑定了名称where,则它们会生成相同的代码。

在这种情况下,您想要使用哪一个完全取决于您。两者都是惯用的Haskell。人们通常会选择在他们工作的环境中看起来更好的一面。

人们使用访问器函数的主要原因是简洁性,当记录有很多字段,模式匹配很大,并且因为它们是实际函数 - 它们可以传递给它们的类型适合的任何高阶函数。您不能将模式匹配作为不同的构造传递。