[Haskell-cafe] Investigating single-letter type variables
Tikhon Jelvis
tikhon at jelv.is
Thu Aug 10 22:43:54 UTC 2017
I've tried using longer type variable names in some of my personal projects
and found a surprising problem: it became harder to tell types from
value-level expressions at a glance. In a lot of cases, I actually found
the resulting code harder to read on net.
There are still times when I use longer type variable names in my code, but
I now think that single-letter names are actually a good default—I need a
good reason to deviate from them.
I think this happens because type signatures tend to be short, relatively
self-contained and often repeated. I want to be able to parse type
signatures quickly, at a glance. Longer type variables might be clearer the
first time you encounter a library, but they often become a pain once
you're familiar with it. (I follow the same reasoning for using short names
for function arguments and local definitions that are used in a restricted
scope.)
:browse through Parsec and consider how many ParsecTs you see, often with
multiple in a single type signature. With this much repetition, variables
consistently named by connection become useful. Sure, you might need to
learn the convention, but the up-front work pays off for itself in any
non-trivial use of the library. Of course, there should also be clear
documentation on the type definition defining what the variables mean.
Gabriel Gonzalez's Pipes library is a perfect example of how this can be
done.
On Aug 10, 2017 6:32 PM, "Jeffrey Brown" <jeffbrown.the at gmail.com> wrote:
> Haskellers tend to use uninformative single-letter type variables. A case
> in point:
>
> Megaparsec> :i ParsecT
>
> type role ParsecT nominal nominal representational representational
> newtype ParsecT e s (m :: * -> *) a ...
>
> I've gotten used to the conventions that "a" stands for anything and "m"
> stands for monad -- but without digging into the code it wasn't initially
> obvious to me whether "s" stood for stream or state.
>
> Single-letter type variables don't seem to always be the standard, though:
>
> Megaparsec> :i between
> between :: Applicative m => m open -> m close -> m a -> m a
> -- Defined in ‘Control.Applicative.Combinators’
>
> My questions are: (1) Are the brevity gains worth the confusion costs? (2)
> If I'm looking at a new library for the first time and trying to figure out
> what a type variable stands for, is there a canonical way to do it?
> Flailing through documentation at random? Unifying types by hand?
>
> --
> Jeff Brown | Jeffrey Benjamin Brown
> Website <https://msu.edu/~brown202/> | Facebook
> <https://www.facebook.com/mejeff.younotjeff> | LinkedIn
> <https://www.linkedin.com/in/jeffreybenjaminbrown>(spammy, so I often
> miss messages here) | Github <https://github.com/jeffreybenjaminbrown>
>
>
> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20170810/eaff9dc3/attachment.html>
More information about the Haskell-Cafe
mailing list