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.
Overview. 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.
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.
Record accessors are just Haskell functions which are automatically generated by the compiler. As such, they are used like ordinary Haskell functions. By naming fields, we can also use the field labels in a number of other contexts in order to make our code more readable.
Haskell guards are used to test the properties of an expression; it might look like an if-else statement from a beginner's view, but they function very differently. Haskell guards can be simpler and easier to read than pattern matching .
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With