Haskell:喜欢模式匹配还是成员访问?

stu*_*ith 13 haskell coding-style

假设我的Vector数据类型定义如下:

data Vector = Vector { x :: Double
                     , y :: Double
                     , z :: Double
                     }
Run Code Online (Sandbox Code Playgroud)

使用成员访问来定义函数是否更常见:

vecAddA v w
    = Vector (x v + x w)
             (y v + y w)
             (z v + z w)
Run Code Online (Sandbox Code Playgroud)

或者使用模式匹配:

vecAddB (Vector vx vy vz) (Vector wx wy wz)
    = Vector (vx + wx)
             (vy + wy)
             (vz + wz)
Run Code Online (Sandbox Code Playgroud)

(如果我的任何术语不正确,请道歉).

val*_*man 12

我通常会使用模式匹配,特别是因为你使用了所有构造函数的参数,并且它们不是很多.此外,在此示例中,这不是问题,但请考虑以下事项:

data Foo = A {a :: Int} | B {b :: String}

fun x = a x + 1
Run Code Online (Sandbox Code Playgroud)

如果你使用模式匹配来做Foo类型的工作,你就是安全的; 无法访问不存在的成员.另一方面,如果使用访问器函数,则调用fun (B "hi!")此处等某些操作将导致运行时错误.

编辑:虽然它当然很可能忘记在一些构造函数上匹配,但模式匹配使得它非常明确,所发生的事情取决于使用的构造函数(您还可以告诉编译器检测并警告您不完整的模式)而使用一个函数提示更多,任何构造函数去,IMO.

如果你只想获得一个或几个构造函数(可能很多)参数并且你知道使用它们是安全的(没有在错误的构造函数上使用访问器的风险,例如在示例中),最好保存访问器.)


Pet*_*ann 7

另一个次要的"真实世界"论点:一般来说,拥有如此短的记录条目名称并不是一个好主意,因为短名称喜欢xy经常最终用于局部变量.

所以这里的"公平"比较是:

vecAddA v w 
  = Vector (vecX v + vecX w) (vecY v + vecY w) (vecZ v + vecZ w)
vecAddB (Vector vx vy vz) (Vector wx wy wz) 
  = Vector (vx + wx) (vy + wy) (vz + wz)
Run Code Online (Sandbox Code Playgroud)

我认为模式匹配在这种类型的大多数情况下都胜出.一些值得注意的例外:

  • 您只需要访问(或更改!)较大记录中的一个或两个字段
  • 您希望保持灵活性以便稍后更改记录,例如添加更多字段.