
On Fri, Dec 18, 2020, at 08:07, Simon Marlow wrote:
On Fri, 18 Dec 2020 at 03:43, Eric Seidel
wrote: In my experience, FFI is the kind of extension that you want to isolate to a single module, and like Cale (or Iavor with the fancier type system extensions) I like the indicator at the top of the file that this module will be dealing with FFI concerns.
I've seen other people express this viewpoint, and I'd like to understand it a bit more. In what way do you see the LANGUAGE pragma at the top of the module as being useful?
To me it's just noise, and unnecessary friction on the developer's workflow. I see LANGUAGE pragmas as useful for experimental or new extensions, when we want to know what code might break if we change it, or we want to add a new extension without breaking old code, or for extensions that we need to be opt-in for a good reason (e.g. TemplateHaskell, which has a significant impact on how we compile things). For long-standing stable extensions, especially ones that are already guarded by syntax, I think LANGUAGE is hurting rather than helping.
I think LANGUAGE pragmas serve two separate purposes, which is the source of the confusion. 1. They can guard new and experimental extensions that aren't ready for inclusion into a standard. This seems to be an uncontroversial use of LANGUAGE. 2. They can also act as a sort of language level in the style of Racket. This is the purpose of extension bundles like Haskell2010 and GHC2021. I think when people say they like the LANGUAGE pragmas at the top of a module, they're referring to use case (2). To be fair, we have very few language extensions currently that act in this way, and FFI is not one of them. But what I think people really want when they make this argument is to have *more* category (2) extensions. So rather than writing {-# LANGUAGE GHC2021 #-} {-# LANGUAGE FFI #-} {-# LANGUAGE UnboxedSums #-} {-# LANGUAGE UnboxedTuples #-} ... we would write {-# LANGUAGE GHC2021 #-} {-# LANGUAGE LowLevelHaskell #-} where LowLevelHaskell implies a coherent set of extensions for dealing with low-level details, and also signifies (much better than the individual extensions) that we should adopt a different mindset when working in this module. Does that make more sense?
In that sense, FFI feels a lot like MagicHash to me, a very important and useful extension, but one that you don't want (or at least don't *need*) enabled everywhere. So it's interesting to me that while FFI has 8 votes now, MagicHash (and UnboxedTuples and UnboxedSums) only has a single vote.
To some extent this is historical. Unboxed and unlifted types were always seen as "GHC extensions" to standard Haskell. Another compiler would very likely have a different way of defining primitive operations, and may or may not have explicit unboxed types. With GHC, the goal has always been to provide ways to do what you want without using these extensions, and over time the use of these has become more concentrated in the low-level libraries, as it should be. For those reasons I'm happy for the unboxed/unlifted family of extensions to remain opt-in. The FFI is a different matter: it was designed to be something that any compiler could implement regardless of its choice of low-level primitives and types.
That's an interesting point, but I think that since we're working on GHC2021 rather than Haskell2021, we shouldn't feel uncomfortable including very GHC-specific extensions. Eric