给定具有记录语法的示例数据类型:
data VmInfo = VmInfo {infoVid :: String
,infoIndex :: Int
,infoPid :: Int
,infoExe :: String
} deriving (Show)
Run Code Online (Sandbox Code Playgroud)
和(vmInfo :: String - > VmInfo)函数,它生成并返回上面给定vm name作为字符串的数据结构.
我可以看到两种方法来提取VmInfo数据类型的各个部分.
(VmInfo vid _ _ _) <- vmInfo vm
Run Code Online (Sandbox Code Playgroud)
这只是一种模式匹配.而......
vid <- infoVid <$> vmInfo vm
Run Code Online (Sandbox Code Playgroud)
使用记录语法编译生成的函数.
问题很简单:哪种方法更受欢迎?
打字量明智,他们是相同的,所以我正在寻找速度和正确/最佳实践.
我假设模式匹配会更快,但那么记录语法的重点是什么?
谢谢.
这些在语义上不相同.
我们来看第一个例子:
(VmInfo vid _ _ _) <- vmInfo vm
Run Code Online (Sandbox Code Playgroud)
这在绑定操作中执行模式匹配.有两个结果.第一个vmInfo vm是评估动作结果的构造函数.这意味着如果vmInfo以类似行结束return undefined,则通过评估抛出的异常undefined将在此模式匹配时发生,而不是稍后使用vid.第二个是如果模式匹配被反驳(模式匹配与值不匹配),fail将使用模式匹配错误文本调用monad的实例.在这种情况下,这是不可能的,但通常可以在绑定模式匹配构造函数时使用.
现在,进入下一个例子:
vid <- infoVid <$> vmInfo vm
Run Code Online (Sandbox Code Playgroud)
根据定义<$>,这将在动作返回的值(而不是效果)中完全是懒惰的.如果vmInfo结束return undefined,那么在undefined你做了一些使用了值的东西之前,你不会得到评估的异常vid.此外,如果infoVoid有能力抛出任何异常,它们最终都不会发生,直到使用vid最佳情况.
有趣的是,这些差异仅存在于monadic绑定的范围内.如果vmInfo是纯粹的,并且您vid在一个let或where表达式中绑定了名称,它们将生成相同的代码.
在这种情况下,您想要使用哪一个完全取决于您.两者都是惯用的Haskell.人们通常会选择在他们工作的环境中看起来更好的东西.
人们使用访问器函数的主要原因是简洁性,当记录有很多字段时模式匹配很大,并且因为它们是实际函数 - 它们可以传递给它们的类型适合的任何高阶函数.您不能将模式匹配作为不同的构造传递.