The HasField
typeclass from DA.Record
is perfect for this!
HasField
gives you getter and setter functions for each record field automatically. The stdlib documentation is a bit lacking currently, so let me try to explain how you can use it.
HasField x r a
is a typeclass that takes three parameters. The first parameter x
is the field name, the second parameter r
is the record type, and the last parameter a
is the type of the field in this record. For example, if I define a type:
data MyRecord = MyRecord with
foo : Int
bar : Text
Then I get, for free, the following HasField instances:
HasField "foo" MyRecord Int
HasField "bar" MyRecord Text
If I want to get a value using HasField, I can use the getField
function:
getFoo : MyRecord -> Int
getFoo r = getField @"foo" r
getBar : MyRecord -> Text
getBar r = getField @"bar" r
Note that this uses the “type application” syntax (f @t
) to specify the field name.
Likewise, if I want to set the value in the field, I can use the setField
function:
setFoo : Int -> MyRecord -> MyRecord
setFoo a r = setField @"foo" a r
setBar : Text -> MyRecord -> MyRecord
setBar a r = setField @"bar" a r
Note that in all these examples I don’t have to pass in the arguments explicitly. I could have written it this way:
getFoo : MyRecord -> Int
getFoo = getField @"foo"
getBar : MyRecord -> Text
getBar = getField @"bar"
setFoo : Int -> MyRecord -> MyRecord
setFoo = setField @"foo"
setBar : Text -> MyRecord -> MyRecord
setBar = setField @"bar"
So to answer the original question, you can use setField @"a"
to set the "a"
field in your record. And this will work for any record type with an "a"
field.
HasField
is actually part of Daml’s built-in mechanism for record handling, and it’s used by the Daml compiler, so it’s something that is specifically optimized in the Daml compiler. As long as the record type is fixed (i.e. not polymorphic), it should be as efficient as writing a record get/set manually. So, compared to using a Lens library, this shouldn’t have any negative performance impact.