[Haskell-cafe] Generic "annotations" on type definitions
Olaf Klinke
olf at aatal-apotheke.de
Sat Sep 10 20:37:43 UTC 2022
On Sat, 2022-09-10 at 15:20 -0400, Will Yager wrote:
> Doesn't this require TH? A primary constraint here is using generics only, since TH has many undesirable properties.
>
> In the original question, I gave an unfair advantage to Rust, because it uses macros, which are similar to TH. Java's system is perhaps a fairer comparison, although it works mostly via runtime inspection.
>
> The idea is to provide information about a type to Generic, without changing the way that type behaves for programmers.
>
> Will
Since your question is about choices of display/input, how about
delaying the choice to the call site? To use your example, the UI
generator knows that a Bool can be used with either check box or radio
button, and the programmer must provide the choice via a settings
record at every instance. This would potentially reduce clutter, as for
many types there might only be one sensible UI choice available, hence
a Data.Default.def suffices. The (admittedly hard) problem then is that
the shape of the settings record must match the shape of the displayed
type. In Haskell pseudocode:
instance UI Bool where
type UISettings Bool = RadioButton | CheckBox
defaultUISettings = CheckBox
instance (UI a, UI b) => UI (a :+: b) where
type UISettings (a :+: b) = (UISettings a :*: UISettings b)
-- must provide settings for both options
inputForm :: UI a => UISettings a -> Form a
I have personal interest in getting to work what you propose, so let's
collaborate. Maybe Yesod's Form Monad is a good starting point for a
proof-of-concept?
Olaf
>
> > On Sep 10, 2022, at 13:26, Olaf Klinke <olf at aatal-apotheke.de> wrote:
> >
> >
> > > Hello all,
> > >
> > > I was recently thinking about a generic programming application
> > > (auto-generating UI code from data definitions) that would benefit from the
> > > ability to "annotate" data definitions. For example, let's say you have a
> > > type
> > >
> > > data Foo = Foo {barred :: Boolean}
> > >
> > > You are (auto-)generating a UI to display and manipulate `Foo`s. Perhaps
> > > the generic UI code defaults to making a check-box for Boolean values, but
> > > you would rather have it be a radio button. It would be advantageous to be
> > > able to write something like e.g.
> > >
> > > data Foo = Foo {barred :: Boolean # RenderMode RadioButton}
> > >
> > > In many languages, you have the ability to annotate data fields in a way
> > > which has no bearing whatsoever on the first-order behavior or
> > > representation of the type, and is only reflected via the language's
> > > generic programming API. For example, in Java, you have
> > >
> > > class Foo {
> > > @RenderMode(RadioButton)
> > > bool barred;
> > > }
> > >
> > > And in Rust, you have
> > > struct Foo {
> > > #[render_mode(radio_button)]
> > > barred : bool
> > > }
> > >
> > > In Haskell, I do not believe we have any such system in place for
> > > interfacing with Generics.
> > >
> > > The closest I am familiar with is from the optparse-generic package, where
> > > you write code of the form
> > >
> > > data Foo w = Foo {barred :: w ::: Boolean <?> RenderMode RadioButton}
> > >
> > > See
> > > https://hackage.haskell.org/package/optparse-generic-1.4.8/docs/Options-Generic.html#t::
> > > ::
> > >
> > > This is basically a clever way to sort of re-create what we have available
> > > in Rust or Java, using type families, but with the annoying downside that
> > > it makes interacting with your type in normal code much more cumbersome,
> > > and is also relatively confusing to read and write.
> > >
> > > Compare Rust's Clap package, which is very similar to optparse-generic, but
> > > more convenient to work with because the annotations don't impact normal
> > > usage of the type.
> > >
> > > See https://docs.rs/clap/latest/clap/#example
> > >
> > > Would it be technically feasible to add such a thing to GHC's Generics
> > > support? I could imagine something like updating the GHC.Generics Meta
> > > type's MetaCons constructor to
> > >
> > > MetaCons Symbol FixityI Bool *[Annotation]*
> > >
> > > Best,
> > > Will
> >
> > Why not use special syntax in comments, like we do for Haddock,
> > doctests etc.
> >
> > data Foo = Foo {
> > barred :: Boolean -- ^ #GUI[RenderMode RadioButton]
> > }
> >
> > There is a functional language capable of auto-generating input forms:
> > Clean https://clean.cs.ru.nl/Clean with the iTask library on top. It
> > can also generate forms for recursive types. The Dutch coast guard uses
> > it to interactively design queries to a database of marine vessel
> > movements.
> > It'd be cool if Haskell's Generics also could do that.
> >
> > Olaf
> >
More information about the Haskell-Cafe
mailing list