If you’ve used DAML Studio or the command line compiler, you will have noticed that it warns you about potential issues in your code.
In the example above, I get a warning for a redundant import of
Daml.Script and I also get a warning about a pattern match that is not-exhaustive (I didn’t match on
These are not fatal errors. The compiler can still produce a DAR and you can test out how your UI works against this model. However, they are usually issues worth investigating before you merge your changes since they either indicate bad practices (redundant imports) or point to actual errors (non-exhaustive pattern matches).
Turning warnings into errors
While it is convenient to test out models that still have warnings, you probably don’t want to commit them. To enforce that you can make the compiler fail if there are any warnings. You can then use this in CI so any builds with warnings will fail and no warnings accidentally make it through to the code that you deploy to production. All you need to change here is to switch from
daml build to
daml build --ghc-option=-Werror and all warnings will instead result in fatal errors!
Enabling additional warnings
The default set of warnings enabled by the DAML compiler is fairly conservative. Especially, when you are just starting out seeing a huge set of warnings can easily be overwhelming and distract from what you are actually working on. However, as you get more experienced and more people work on the same projects enabling additional warnings (and enforcing their absence in CI) can be useful.
All of these warnings can be enabled by adding
--ghc-option=-W<warningname> to the list of
build-options in your
daml.yaml. You can disable warnings via
This warning tells you if you have unused top-level definitions, i.e., dead code that is not used anywhere and can be deleted. Note that this only works if you specify the list of exported definitions explicitly. Otherwise all top-level definitions are exported implicitly so they could be used from another module and therefore cannot necessarily be deleted. To specify them explicitly switch from
module A where
module A (export1, export2) where.
Note: This requires SDK 1.3.0-snapshot.20200623.4546.0.4f68cfc4 or newer to work properly. For older versions, templates produce false positives. Special thanks to @shaynefletcher for fixing this.
-Wunused-matches tells you about patttern matches where you bound a variable but didn’t use it. This can indicate that you passed an unused parameter to a function, e.g.,
f x = 0
Here you will get a warning about
x being unused. If you do this intentionally you can replace the
x by an underscore or any variable name starting with an underscore, e.g.,
f _x = 0
This is similar to
unused-matches but specific to
f p = do cid <- submit p (createCmd …) pure ()
Here you will get a warning that
cid is unused. As with
unused-matches you can silence it by prefixing the variable with an underscore.
By default, the compiler warns you about non-exhaustive pattern matches. But it doesn’t warn you in places where you can only specify one pattern, e.g., a lambda or a
incomplete-uni-patterns also warns about those cases.
f = (\(Left x) -> x)
As the name suggests, this warning warns you about redundant constraints on a definition, e.g.,
f : Eq a => a -> a f x = x
There is no reason to add the
Eq a constraint here since we are not using
/=. The extra constraint makes our function less useful and also incurs a runtime overhead.
While the DAML compiler is often able to infer the type of an expression, it is good practice to annotate top-level definitions with an explicit type signature to make your code easier to read, get better compile errors on type mismatches and potentially avoid runtime overhead from making your function more general than you intended to.
-Wmissing-signatures warns you about any top-level definition without a type signature. Note that you need to write the type signature separately to silence the warning.
f (x: Int) : Int = x + 1
will still produce the warning while
f : Int -> Int f x = x + 1
Enabling all common warnings
Enabling all warnings individually can get tedious. Instead you can add
--ghc-option=-Wall to your
daml.yaml enable all of them and then selectively disable warnings via
--ghc-option=-Wno-<warningname> that you don’t want to use on your project
What are your favorite warnings?
Did i miss any that you consider helpful? Which one helps you the most in writing better code with less errors?