Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell Records- setting/getting using string fieldname

Tags:

haskell

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.

like image 214
jamshidh Avatar asked Jan 17 '26 00:01

jamshidh


1 Answers

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.

like image 158
J. Abrahamson Avatar answered Jan 19 '26 19:01

J. Abrahamson