[Haskell-cafe] Diving into the records swamp (possible GSoC project)

Adam Gundry adam.gundry at strath.ac.uk
Sat Apr 27 10:52:48 CEST 2013


Hi Johan,


On 26/04/13 20:46, Johan Tibell wrote:
> Hi Adam,
> 
> Since we have already had *very* long discussions on this topic, I'm
> worried that I might open a can of worms be weighing in here, but the
> issue is important enough to me that I will do so regardless.

I'm the one busily opening this particular can. It's good to know it's
an important one though!

Thanks for characterising the problem so neatly:

> Instead of endorsing one of the listed proposals directly, I will
> emphasize the problem, so we don't lose sight of it. The problem people
> run into *in practice* and complain about in blog posts, on Google+, or
> privately when we chat about Haskell over beer, is that they would like
> to write a record definition like this one:
> 
>     data Employee = Employee { id :: Int, name :: String }
> 
>     printId :: Employee -> IO ()
>     printId emp = print $ id emp
> 
> but since that doesn't work well in Haskell today due to name
> collisions, the best practice today is to instead write something like:
> 
>     data Employee = Employee { employeeId :: Int, employeeName :: String }
> 
>     printId :: Employee -> IO ()
>     printId emp = print $ employeeId emp
> 
> The downsides of the latter have been discussed elsewhere, but briefly
> they are:
> 
>  * Overly verbose when there's no ambiguity.
>  * Ad-hoc prefix is hard to predict (i.e. sometimes abbreviations of the
> data type name are used).
> 
> The important requirement, which might seem a bit obvious, is that any
> solution to this problem better not be *even more* verbose than the
> second code snippet above. If I understand the SORF proposal correctly,
> you would write:
> 
>     data Employee = Employee { id :: Int, name :: String }
> 
>     printId :: Employee -> IO ()
>     printId emp = print $ emp.id <http://emp.id>
> 
> Is that correct or do you have to replace 'Employee' with 'r { id :: Int
> }' in the type signature of 'printId'?

That's correct. The most general type (inferred if the annotation is
omitted) will be something like

printId :: r { id :: Int } => r -> IO ()

but you are free to declare a more specific type in the usual way, much
as if the constraint was 'Show r', say.


> The discussions about an overhauled record system also involve lots of
> talk about record sub-typing, extensible records, and other more
> advanced features. I'd like to point out that there doesn't seem to be a
> great demand for these features. They might be nice-to-haves or might
> fall out naturally from a solution to the namespacing problem above, but
> they are in fact not needed to solve the common problem people have with
> the Haskell record system.

Thanks, I take your point. My proposal is to implement a good solution
to the problem you've outlined; I don't think we should go all the way
to extensible records just yet, if at all.


> Cheers,
>   Johan
> 

All the best,

Adam



More information about the Haskell-Cafe mailing list