• she/her

Principal engineer at Mercury. I've authored the Dhall configuration language, the Haskell for all blog, and countless packages and keynote presentations.

I'm a midwife to the hidden beauty in everything.

💖 @wiredaemon


discord
Gabriella439
discord server
discord.gg/XS5ZDZ8nnp
location
bay area
private page
cohost.org/newmoon

mehbark
@mehbark

this is not meant to be combative! i really like haskell, and i've been liking it more and more the more i use it more, more. don't feel obligated to answer these at all! i just wanted to put them all in one place. these are in order of when i put them and very, uh, unrefined

  • are there any language extensions i should always use?
  • are there any language extensions i should never use?
  • speaking of language extensions, is any implementation other than GHC worth using?
  • arrows are very cool! i printed out the original paper and read it a while ago, but i'm still very shaky on them. i'll read this. they seem pretty hard to use! are they worth it?
    • i do love that ->s are arrows, which makes stuff like (&&&) beautifully general
  • is proc notation worthwhile?
  • are any alternate preludes worth the effort? the idea of using decades of hindsight seems nice
  • was it worth changing(?) Monad to require Applicative, which requires Functor?
  • dependent haskell. i read some of the writing on that on serokell's blog. how's that going?
  • is there a more lightweight (in terms of project structure) alternative to cabal? is cabal even the thing for dependencies? i should try nix for this hm
  • my vscode setup for haskell is so brittle! sometimes two or three instances will start up and i have to restart vscode. this isn't a question, sorry, i just really need to fix this, lol. i'll probably try to get emacs up to par
  • speaking of dependencies, is the (thankfully) built-in Parsec good enough, or should i learn {mega,atto,giga???}parsec/something else? (i think i'll try megaparsec out for errors' sake)
  • speaking of preludes like five questions ago, should i be using Text pretty much all the time?
    remarkably, i am out of questions for the moment, so i guess i'll publish this now

karkat's birthday update:
there are two great sets of answers by

if you've read this far, read both of these! if you haven't read this far, what?

i'm still going to barf questions (and answers if and when i find them) here:

  • (<$) is quite useful. i've mainly seen it when parsing enums. the docs say
    The default definition is fmap . const, but this may be overridden with a more efficient version.
    but it's hard to think of (or find) instances where a more efficient version is possible. - i did find a [specialized definition](https://hackage.haskell.org/package/base-4.20.0.1/docs/src/Data.Functor.Product.html#line-82) for Product! but i have no idea if it's actually more efficient lol

Jun 17 00:24 00:29 update:

  • i was annoyed by ghc (-Wall)'s constant warnings about shadowing variable bindings, so i looked up how to turn it off, which led me to this reddit thread. the comments convinced me to fix my code instead of configuring ghc (i have done recursion when i didn't mean to multiple times). do you think haskell would be better if recursive bindings had to be explicit? idk! i can live with letrec and i have written dozens of bytes of ocaml, but it feels nice to be concise

fullmoon
@fullmoon

(anyone reading this should feel free to ask my account this sort of stuff)

are there any language extensions i should always use?

I'm not sure I can provide a definitive answer to this question, but here are some extensions that (A) I enable quite frequently in my code and (B) have basically no downside as far as I'm concerned:

  • BlockArguments
  • DerivingStrategies /DeriveGeneric / DeriveAnyClass / GeneralizedNewtypeDeriving
  • NamedFieldPuns
  • TypeApplications

are there any language extensions i should never use?

The only one that comes to mind for me IncoherentInstances. This is almost always a mistake to enable and there's usually a better alternative.

speaking of language extensions, is any implementation other than GHC worth using?

no

arrows are very cool! i printed out the original paper and read it a while ago, but i'm still very shaky on them. i'll read this. they seem pretty hard to use! are they worth it?

no. most cases where people want Arrow they'd be better served by Category + Applicative

is proc notation worthwhile?

no. again, Category + Applicative is typically better and do notation + ApplicativeDo is typically a better solution than proc notation

are any alternate preludes worth the effort? the idea of using decades of hindsight seems nice

maybe relude, but i personally don't use alternative preludes. i don't feel like they add a lot of value. i prefer to explicitly import all the functionality i need from the original packages even if it means a lot of imports

was it worth changing(?) Monad to require Applicative, which requires Functor?

yes. this leads to simpler constraints on a LOT of functions. it also makes stuff like ApplicativeDo much safer to enable

dependent haskell. i read some of the writing on that on serokell's blog. how's that going?

no idea. i think it will never materialize

is there a more lightweight (in terms of project structure) alternative to cabal? is cabal even the thing for dependencies? i should try nix for this hm

no. just bite the bullet and use plain old cabal. don't mess around with other stuff until you're very comfortable using cabal. trust me on this one

my vscode setup for haskell is so brittle! sometimes two or three instances will start up and i have to restart vscode. this isn't a question, sorry, i just really need to fix this, lol. i'll probably try to get emacs up to par

i use ghcid for my haskell coding

speaking of dependencies, is the (thankfully) built-in Parsec good enough, or should i learn {mega,atto,giga???}parsec/something else? (i think i'll try megaparsec out for errors' sake)

use megaparsec if you need LL parsing (which is typically what you want) and use Earley if you need LR parsing (which is typically only what you want if you're implementing a programming language)

speaking of preludes like five questions ago, should i be using Text pretty much all the time?

yes. basically never use String except in cases where you have to and make sure all of your public function types use Text instead of String


You must log in to comment.

in reply to @mehbark's post:

are there any language extensions i should always use?

There are a few you'll probably need a lot but most of them are in GHC2021 these days so you can probably just enable that

are there any language extensions i should never use?

Eh, not really. There used to be a few but IncoherentInstances is deprecated (and you now put the annotations on the instance instead if you want what it did) and ImpredicativeTypes has been replaced with a feature that Actually Works. There are a few where you might not want to turn them on so they warn you if what you're doing is not actually what you want (e.g. UndecidableInstances/UndecidableSuperClasses. Maybe MagicHash as well?) but they're still useful if you do need them.
I guess you probably shouldn't turn on LinearTypes though unless you're okay with your code breaking in later versions of ghc since it's still pretty experimental

speaking of language extensions, is any implementation other than GHC worth using?

GHCJS :)

arrows are very cool! i printed out the original paper and read it, but i'm still very shaky on them. i'll read this they seem pretty hard to use! are they worth it?

They're cute but it's pretty rare to see them in the wild tbh. I think most of their uses have been replaced by Applicatives which are much simpler and more general (Arrows sit somewhere in between Applicatives and Monads iirc). Applicatives also let you use do notation instead of weird point-free contortions or whatever proc notation is ^^

is proc notation worthwhile?

I'm pretty sure I remember reading something from Alexis King a few years ago about how proc notation is buggy and fundamentally broken in a way where noone really knows what the correct answer should be. And I don't think I've ever seen it in an actual code base :/

are any alternate preludes worth the effort? the idea of using decades of hindsight seems nice

Well I'm working on one :p (got a little distracted but I'd like to finish it some time)
But more seriously, relude is great!

was it worth changing(?) Monad to require Applicative, which requires Functor?

So this happened before my time with Haskell but at least from my perspective, having Applicative as a superclass of Monad is great and definitely worth it!

dependent haskell. i read some of the writing on that on serokell's blog. how's that going?

Slowly mostly. ^^ RequiredTypeArguments is in 9.10.1 though!

is there a more lightweight (in terms of project structure) alternative to cabal? is cabal even the thing for dependencies? i should try nix for this hm

Hmm what do you dislike about cabal? There are also stack and hpack if those are more your thing. hpack generates cabal files for you so (among other things) you don't need to list every module manually. Stack uses hpack by default and also manages the entire installation for you by using a curated package set by default (so as long as you stick to commonly used packages you will never get package conflicts). It even automatically installs the right ghc version per project

my vscode setup for haskell is so brittle! sometimes two or three instances will start up and i have to restart vscode. this isn't a question, sorry, i just really need to fix this, lol. i'll probably try to get emacs up to par

Yeah no that's normal ^^ IME HLS will just start working correctly at some point but until then you'll need to restart things a lot. You can do Ctrl+Shift+P "Reload Window" instead of manually restarting VSCode though (There is also a "Reload Haskell Language Server" Command but that one doesn't always work perfectly).

speaking of dependencies, is the (thankfully) built-in Parsec good enough, or should i learn {mega,atto,giga???}parsec/something else? (i think i'll try megaparsec out for errors' sake)

Uh, parsec isn't built-in. ^^ There is ReadP but it's pretty bad and terribly slow. Regular parsec is fine though, although I think megaparsec is slightly more popular and just a bit better in most aspects? attoparsec is focused more on performance so if you want good error messages you should probably stick to megaparsec. But I know that @fullmoon likes Earley and I usually use happy

speaking of preludes like five questions ago, should i be using Text pretty much all the time?

YES. String is Bad and will tank your performance. relude makes it pretty easy to use Text though!

thank you so much for these detailed answers! a lot of these would have taken me a while to figure out. here's some thoughts/clarifications:

  • i had no idea Applicative came after Arrow, that explains why i use Applicative a lot and Arrow, uh, not much
  • sucks that proc notation is buggy :(
  • my main memory of cabal is it generating a larger and more fragmented folder structure than i'd like with like three yaml files. guess what, that was stack. oops! cabal init --exe seems like the sweet spot for me
  • i've had to unbork vscode so many times that i learned to use Developer: Reload Window long ago, lol
  • i have no idea why, but i can just import Text.Parsec. i must have globally installed it at some point, but idk how or why

this reply might singlehandedly get me to write haskell again

re cabal: something i really like about using hpack is that it generates the list of files in my project for me. i hate how with cabal i have to go in and manually type out every .hs file in my project to get it to compile them, like bro just look at the folder? i feel like the computer should do this for me.

am i wrong? is there some reason that its good to type all my files in by hand into the .cabal file? or like, am i wrong that i even need to do that?

arrows are very cool! [..] are they worth it?

is proc notation worthwhile?

i recently gave a talk which kind of went into this in the context of bidirectional programming, which i think arrows have a lot of potential for, but currently have some fundamental flaws. you can check out the slides here (though there's no recording and no speakers notes, so some parts might not be well explained, but dw about the details)

tl;dr: arr is a huge problem for all of the domains i'm interested in and proc notation uses arr for everything. i'm hoping to reformulate arrows in a way that solves this issue and allows proc notation for a wider variety of stuff, but my plan is still in the early stages