How to enable language extensions / pragmas project wide by default? - haskell

Is there a way to put {-# LANGUAGE <feature> #-} pragmas in either the:
<project>.cabal, or
stack.yaml
file, to avoid repeating the same header code in every *.hs file of a project?

As #user2407038 said in the comments, you can use the default-extensions field in your <project>.cabal file.
If you wanted to have OverloadStrings and GADTs in all of your modules in the project, you would list it in relevant section of your cabal file (i.e. if you want it for all of your library files, put it in library).
For example:
-- <project>.cabal
...
library
hs-source-dirs: src
default-extensions: GADTs
, OverloadedStrings
...
If you are using a package.yaml configuration file to generate your <project>.cabal file, you can also specify this field there.
-- package.yaml
library:
source-dirs: src
default-extensions:
- OverloadedStrings
- GADTs
exposed-modules:
- MyModule
...

Wow this is annoying. The error message from cabal literally says to use 'extensions:', but you have to use 'default-extensions:'...

Related

When does cabal recompile a module which contains Template Haskell?

I understand that cabal will recompile a module if the interface of any of its dependencies has changed. It seems that this simple rule does not hold if the module contains Template Haskell. In that case, even just adding a trailing newline character to a file in the module's (transitive) dependencies will cause the cabal to recompile the file.
Minimal example:
file: Foo.hs
module Foo where
foo = "foo"
file: FooTH.hs
{-# LANGUAGE TemplateHaskell #-}
module FooTH where
import Data.Bifunctor.TH
import Foo
data FooPair a b = FooPair a b
$(deriveBifunctor ''FooPair)
file: MCVE.cabal
name: MCVE
version: 0.1.0.0
synopsis: MCVE
license: MIT
license-file: LICENSE
author: tarleb
maintainer: tarleb#example.com
build-type: Simple
extra-source-files: CHANGELOG.md
cabal-version: >=1.10
library
exposed-modules: Foo
, FooTH
build-depends: base >=4.8 && <4.13
, bifunctors
default-language: Haskell2010
Adding a newline to Foo.hs, e.g. by running echo "\n" >> Foo.hs, will cause recompilation of module FooTH. This ceases to happen if the TH line in FooTH is commented out.
What is the reason for this, and is there a way to avoid this unnecessary recompilation?
There's a feature in Template Haskell called addDependentFile, which adds metadata to the .hi file indicating that the source file in question depends on another file as well. To my knowledge, Cabal will always ask GHC to try to build, though it may have more intelligent logic. Stack tries to bypass that process, and has logic to parse the addDependentFile information out.

Is START_FILE a GHC pragma?

Who could provide information regarding START_FILE pragma?
The is no word about START_FILE in GHC Pragmas Documentation. Nevertheless it seems to be widely used [1], [2], [3].
Unfortunately ghc 8.2.2 does not compile following code[1].
{-# START_FILE main.hs #-}
main = readFile "file.txt" >>= putStr
{-# START_FILE file.txt #-}
Hello, world!
No, this is an extension specific to School of Haskell Markdown. It's used to provide several "files" in a single Markdown code block.
It's not "widely used" outside of School of Haskell for that reason. When reading such code snippets, simple treat everything after a START_FILE pragma as if it was in a file with the name indicated as the parameter (if it indicates a format like BASE64 you need to put the decoded bytes into the file instead).
This pragma is used by stack templates. You can specify multiple files inside single file with extension .hsfiles by separating files with {-# START_FILE #-} pragma.
stack new PACKAGE_NAME myfiles.hsfiles will create those files (and all directories automatically) according to your layout, if myfiles.hsfiles contains:
{-# START_FILE {{name}}.cabal #-}
name: {{name}}
version: 0.1.0.0
or
{-# START_FILE package.yaml #-}
name: {{name}}
version: 0.1.0.0
See some examples in this repository:
https://github.com/commercialhaskell/stack-templates

Setting compiler options for intero in emacs

When I am developing I like to have -fdefer-type-errors and -XPartialTypeSignatures enabled. Currently I just add
{-# LANGUAGE PartialTypeSignatures #-}
{-# OPTIONS_GHC -fdefer-type-errors #-}
to the top of the file I am working with. However this is not ideal as I often forget to remove these lines once I am done. Is there an option to pass these to intero in emacs?
Updating your cabal file to specify the relevant extensions and ghc-options should work, i.e.:
...
lib
hs-source-dirs: src
ghc-options: -fdefer-type-errors
extensions: PartialTypeSignatures
This can now be archived by setting intero-extra-ghc-options and intero-extra-ghci-options.

How can I add an extra switch in Leksah?

I would like to add an extra switch "-XDeriveDataTypeable" to the compiler.
Otherwise, I would like to able to compile Typeable.
Where can i do that in Leksah?
Generally
Here's a editor/ide-agnostic solution to your problem:
For language extensions, you can add this at the top of the source as a compiler pragma, which I prefer anyway:
{-# LANGUAGE DeriveDataTypeable #-}
instead of -XDeriveDataTypeable on the command line
You can pass other command line options to GHC, like this:
{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
In Leksah
Leksah uses cabal for build configuration, so there's no special Leksah magic, that's all standard, but you can use the package editor as a GUI to edit the cabal file.
2/3 of the way down is the Extensions section where you can specify what language extensions you want.

Replace compiler when building Haskell project with Cabal

Is it possible somehow to configure cabal project to use different compiler than GHC? Additional is it possible to control this by some flags?
I want to compile my project with GHC or Haste (to JavaScript) based on some compilation flags.
It would be ideal if I could set my cabal configuration or my custom script to do something like:
-- target JS
cabal configure --target=js
cabal build
-- target Native
cabal configure --target=native
cabal build
To build a Cabal project with either GHC or Haste, use the cabal binary for the former, and haste-inst (comes with haste) for the latter.
To have conditional code in in your modules, add {-# LANGUAGE CPP #-} and use #ifdef __HASTE__, which will only be defined by haste, but not by GHC. Note that __GLASGOW_HASKELL__ is defined in both cases (which makes sense, as haste builds on GHC for large parts of the compilation). So you would use it like
{-# LANGUAGE CPP #-}
module Module where
compiler :: String
#ifdef __HASTE__
compiler = "haste"
#else
compiler = "GHC"
#endif
Theoretically, for conditional settings in the Cabal file something like this should work:
library
exposed-modules:
Module
if impl(ghc)
exposed-modules:
Module.GHC
if impl(haste)
exposed-modules:
Module.GHC
build-depends: base ==4.6.*
but it seems that even with haste-inst, impl(ghc) is true; bug report is filed.
While it's currently not possible to use impl(haste) in your cabal files, you can now check for flag(haste-inst) to see if your package is being built using haste-inst.

Resources