Problem: I have different record types with many common fields. How could I "include" the common fields in the record type definitions?
Example:
newtype RecordType1 = RecordType1 { a :: Int, b :: Int, y :: String }
newtype RecordType2 = RecordType2 { a :: Int, b :: Int, z :: Boolean }
How to write the equivalent in PureScript?
newtype RecordType1 = RecordType1 { CommonFields, y :: String }
newtype RecordType2 = RecordType2 { CommonFields, z :: Boolean }
The type class Union mentioned in An Overview of the PureScript Type System could be what I look for... but it seems to be out since PureScript 0.12.0.
Any recommendations? Is there anything I'm missing?
Thanks!
PureScript has a special syntax for combining records:
Note that the definition of
Commonuses parentheses, not curly braces. That is becauseCommonis a row, not a record. You can make a record out of it though:In fact, the curly braces notation is just syntactic sugar for applying
Recordto a row. An expression{ xyz }gets desugared toRecord ( xyz ).You can use the "pipe" syntax to extend rows as well:
You can also make your record types polymorphic by providing
Commonas a type parameter:This is very handy for writing functions that work with partial records, e.g.:
In this example, the function can work with any record that has a
namefield, regardless of what else it might have.Finally, to express an empty row, use empty parens:
On a slightly unrelated topic, note that records in PureScript are not the same as records in Haskell. For example, above
Record1andRecord2are true PureScript ad-hoc extensible records (something that Haskell doesn't have), butRecordType3is a newtype that has one constructor whose parameter is a record.One important difference is that, unlike Haskell, this wouldn't work:
The expression
w x(or even expressionx.w) doesn't compile, becauseRecordType3is not itself a record, it's a newtype that wraps a record. In order to getwout of it you need to match on the constructor first:Or wrap that as an accessor function:
In practice this is really inconvenient if you're approaching records with a Haskell mindset. Instead, what you want to do in PureScript is prefer "naked" records (like
Record1andRecord2in my example above) and only resort to wrapping them innewtypewhen you really have to.