In many cases it would be useful to be able to set/get a record field via its name as a string (for instance, converting records to/from command line arguments, HTTP headers, SQL query results, or store widgets in a GUI tree in an easy to use record, etc). The functions could have the types
setField::String->Val->Record->Record
getField::String->Record->Val
getFieldNames::Record->[String]
where Val could be something that could convert to other types (string, glib GValue, or even the Convertables I described here)
I've started writing a library that does this, with plans contribute it to the community (it will need some GHC extensions, probably including TemplateHaskell)....
My question- Does something like this already exist? Is there a better way to populate Records from external name/value pairs? I've looked all over and can't find it. (lenses are related, but don't use the string name).
I think this would be useful, but don't want to reinvent the wheel.
You might do something like this using Vinyl, though you'll still need to create strongly type accessors. The advantage is that the type system contains enough information to ensure that you never need to runtime handle Maybe-wrapped lookup failures.
Copying some relevant examples from that link
name = Field :: "name" ::: String
age = Field :: "age" ::: Int
sleeping = Field :: "sleeping" ::: Bool
jon = name =: "jon"
<+> age =: 20
<+> sleeping =: True
type LifeForm = ["name" ::: String, "age" ::: Int, "sleeping" ::: Bool]
jon :: PlainRec LifeForm
wakeUp :: (("sleeping" ::: Bool) ∈ fields) => PlainRec fields -> PlainRec fields
wakeUp = sleeping `rPut` False
jon' = wakeUp jon
> rGet name jon'
"jon"
> rGet sleeping jon
True
> rGet sleeping jon'
False
If you're not willing to do something akin to this, then you're probably going to end up with some kind of runtime failure which means you might as well have type Record = Map String Val.
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