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

r.s*_*cky 6 haskell

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

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)

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

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

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

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

谢谢.

Car*_*arl 8

这些在语义上不相同.

我们来看第一个例子:

(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在一个letwhere表达式中绑定了名称,它们将生成相同的代码.

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

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

  • 使用访问器而不是模式匹配的另一个原因是在维护程序时使代码更加健壮以防止更改数据结构.如果以几乎任何方式更改数据结构,通常所有模式匹配现在都将无法编译.如果您只是在具有多个字段的类型中一次处理少量字段,那么使用访问器意味着对数据结构的更改很可能主要仅影响使用您添加的字段的位置/去除/改变. (7认同)
  • @Ben为了获得两者的优点,`VmInfo {infoVid = vid} < - vmInfo vm`. (7认同)