40

I'm looking for a way to simplify function patterns when the actual data is not required:

data X = A | B String | C Int Int String
myfn :: X -> Int
myfn A = 50
myfn (B _) = 200
myfn (C _ _ _) = 500

Is there a way to make a simpler pattern for matching C, just discarding the values?

hsdev adds a hint "Hint: use record patterns", but Google did not help me there.

Will Ness
  • 62,652
  • 8
  • 86
  • 167
theduke
  • 2,702
  • 4
  • 26
  • 28

1 Answers1

88

You can use record patterns like this:

data X = A | B {name :: String} | C {x::Int, y::Int, name::String}

myfn :: X -> Int
myfn A = 50
myfn B{} = 200
myfn C{} = 500

Record patterns allow you to give names to the fields of the constructors. you can also do things like:

myfn C{name=n} = length n

so you can see that you can pattern match only on the specific field you need.

Note: you can use the empty record pattern even with data types that do not use record syntax:

data A = A Int | B Int Int

myfn A{} = 1
myfn B{} = 2

This is fine. There a number of other extensions related to record patterns:

  • RecordWildCards allows you to write things like C{..} which is equivalent to the pattern: C{x=x, y=y, name=name}, i.e. it matches all fields and you now have in scope x with the value matched for the x field etc.

  • NamedFieldPuns allows you to write C{name} to be equivalent to C{name=name}, so that name is now in scope and contains the value matched for the name field.

Keep in mind that using record patterns doesn't prevent you from using your constructors in a positional way, so you can still write:

myfn (B _) = 200

It only adds functionality.

Bakuriu
  • 85,459
  • 18
  • 168
  • 202
  • Great, thanks. I actually tried C{_} and C{..}, to no avail. Just one character too much. ^^ – theduke Jun 27 '16 at 11:34
  • 6
    Shame that Google doesn't help you much with "haskell record pattern". I've renamed the question, maybe that'll make it more discoverable for others. – theduke Jun 27 '16 at 12:54
  • 1
    @theduke: Note also that you can use the empty record pattern (`B{}`) even if you declared `B` to be a normal, non-record data type. – Lii Jun 27 '16 at 13:05
  • @Lii That is something I didn't think about. I'll add a mention to the answer. – Bakuriu Jun 27 '16 at 13:32
  • @Lili thanks for pointing it out. To me, it was obvious from the answer anyway, though. – theduke Jun 28 '16 at 12:35