[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