Hacker News new | past | comments | ask | show | jobs | submit login

Javadoc-like comments ("Haddocks") are pretty widely used, and Hackage (the Haskell library index) let's you browse them and so on.

See [0] for a good example of well-commented but idiomatic Haskell (a snippet from the popular Megaparsec parser library), which includes things like:

    data ParsecT e s m a
    
    ParsecT e s m a is a parser with
    custom data component of error e, 
    stream type s, underlying monad m
    and return type a.
Admitted, that is a monad transformer, but one-character type variables with human-readable docs are both good for newcomers as well as low-friction for people who are used to the library in question.

(Strawman alert.) It is significantly more work to parse (ha) something like

    ExceptT fooException (StateT fooWorldState underlyingMonad) a
when compared to

    ExceptT e (StateT s m) a
[0]: https://hackage.haskell.org/package/megaparsec-5.2.0/docs/Te...



It's also worth noting that there are conventions around type variable names. If you see an `m`, it's probably a Monad; if you see an `s`, it's probably a stream or a struct or state; `i` is likely being indexed over; the code probably doesn't care what `a` is - the surrounding code can pick it freely. If you need another, advance to the next letter (`b`, `c`, less often `n`, `o`).

Of course, Edward Kmett had a story about winding up with his code telling him `i m a s t a b u`...


f for a functor is also very common, as is k for "continuations", very generally speaking (I think this is a borrowing from Lisps?): one often sees monadic bind defined as

    m >>= k = ...
In a somewhat more esoteric vein, I love the use of w for comonads: the rationale is apparently that it looks like an upside-down m.

> Of course, Edward Kmett had a story about winding up with his code telling him `i m a s t a b u`...

Is that an indexed lens ... parameterized over a monadic type? I'd like a link to the video/article.


Certainly `f` for functor. `k` is more for values than types (you usually know a continuation is some kind of (->)) but they'll often return `r`.

> I love the use of w for comonads: the rationale is apparently that it looks like an upside-down m.

That's my understanding, yeah.

> Is that an indexed lens ... parameterized over a monadic type?

Presumably further parameterized by the focus, the source structure, the target structure, the focus again, the transformed focus, and some third structure.

> I'd like a link to the video/article.

Me too :-P I see a couple references in a google search but I'm not sure where I first heard it.


I want to disagree a lot - the first example is way easier to parse then the second. The names tell me approximately the scope the function applies to, what I'm looking for in the code as "relevant", and which bits are doing what.

The second tells me nothing - how is this intended to be used? What scope is it intended to be used in? Why was it created? Where does it fit in the program flow?


There is a certain amount of familiarity expected, sure. But anyone who has read, say, the Monads chapters in Learn You A Haskell (which is about as nonintimidating as a book can get!) should be able to guess what those types - s and so on - mean. It's akin to the mClassMember/THIS_IS_STATIC_AND_PROBABLY_FINAL conventions in Java (don't quote me on that).

In other words, my thesis is that if you aren't familiar with State, both State s and State fooAppStateType are fairly opaque.

In any case, most of the time one works with a specialized instance, for instance, one might have something likr

    newtype AppState a = 
      AppState {  
        runAppState :: 
          ReaderT Config
            (StateT AppState IO) 
            a 
      }
and then there's no problem at all.

If you're trying to understand how a library works when you're not very fluent in the language, that's what the documentation is there for! Any good library (and this is an area where's lots of room for improvement) should document the types it uses and the idioms that it lends itself to, and as one accrues experience, the whole "learning to see common patterns" takes over. The great thing about a helpful compiler of the Rust/Haskell ilk is that you make fewer mistakes in between (modulo occasionally horrific error messages).

And I'm willing to vouch for this not being expert (ha) blindness - I have only recently become comfortable enough with these things to talk about them.




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: