Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell: Prefer pattern-matching or member access?

Suppose I have a Vector datatype defined as follows:

data Vector = Vector { x :: Double
                     , y :: Double
                     , z :: Double
                     }

Would it be more usual to define functions against it using member access:

vecAddA v w
    = Vector (x v + x w)
             (y v + y w)
             (z v + z w)

Or using pattern-matching:

vecAddB (Vector vx vy vz) (Vector wx wy wz)
    = Vector (vx + wx)
             (vy + wy)
             (vz + wz)

(Apologies if I've got any of the terminology incorrect).

like image 530
stusmith Avatar asked Aug 02 '11 13:08

stusmith


People also ask

Does Haskell have pattern matching?

We use pattern matching in Haskell to simplify our codes by identifying specific types of expression. We can also use if-else as an alternative to pattern matching. Pattern matching can also be seen as a kind of dynamic polymorphism where, based on the parameter list, different methods can be executed.

How does pattern matching work in Haskell?

Pattern matching consists of specifying patterns to which some data should conform and then checking to see if it does and deconstructing the data according to those patterns. When defining functions, you can define separate function bodies for different patterns.

Why ++ is not allowed in pattern matching?

You can only pattern-match on data constructors, and ++ is a function, not a data constructor. Data constructors are persistent; a value like 'c':[] cannot be simplified further, because it is a fundamental value of type [Char] .

What does in do in Haskell?

in goes along with let to name one or more local expressions in a pure function.


1 Answers

I would normally use pattern matching, especially since you're using all of the constructor's arguments and there aren't a lot of them. Also, In this example it's not an issue, but consider the following:

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

fun x = a x + 1

If you use pattern matching to do work on the Foo type, you're safe; it's not possible to access a member that doesn't exist. If you use accessor functions on the other hand, some operations such as calling fun (B "hi!") here will result in a runtime error.

EDIT: while it's of course quite possible to forget to match on some constructor, pattern matching makes it pretty explicit that what happens depends on what constructor is used (you can also tell the compiler to detect and warn you about incomplete patterns) whereas the use of a function hints more that any constructor goes, IMO.

Accessors are best saved for cases when you want to get at just one or a few of the constructor's (potentially many) arguments and you know that it's safe to use them (no risk of using an accessor on the wrong constructor, as in the example.)

like image 198
valderman Avatar answered Sep 26 '22 07:09

valderman