Commit 568736d7 authored by Ben Gamari's avatar Ben Gamari 🐢

users guide: Add documentation for custom compile-time errors

parent f01eb541
......@@ -9599,13 +9599,75 @@ splices.
supported either.
- Type splices: only anonymous wildcards are supported in type splices.
Named and extra-constraints wildcards are not.
::
Named and extra-constraints wildcards are not. ::
{-# LANGUAGE TemplateHaskell #-}
foo :: $( [t| _ |] ) -> a
foo x = x
.. _custom-errors:
Custom compile-time errors
==========================
When designing embedded domain specific languages in Haskell, it is useful to
have something like ``error`` at the type level. In this way, the EDSL designer
may show a type error that is specific to the DSL, rather than the standard GHC
type error.
For example, consider a type class that is not intended to be used with
functions, but the user accidentally used it at a function type, perhaps
because they missed an argument to some function. Then, instead of getting the
standard GHC message about a missing instance, it would be nicer to emit a more
friendly message specific to the EDSL. Similarly, the reduction of a type-level
function may get stuck due to an error, at which point it would be nice to
report an EDSL specific error, rather than a generic error about an ambiguous
type.
To solve this, GHC provides a single type-level function, ::
type family TypeError (msg :: ErrorMessage) :: k
along with a small type-level language (via
``DataKinds`` :ref:`promotion <promotion>`)
for constructing pretty-printed error messages, ::
-- ErrorMessage is intended to be used as a kind
data ErrorMessage =
Text Symbol -- Show this text as is
| forall t. ShowType t -- Pretty print a type
| ErrorMessage :<>: ErrorMessage -- Put two chunks of error message next to each other
| ErrorMessage :$$: ErrorMessage -- Put two chunks of error message above each other
in the ``GHC.TypeLits`` :base-ref:`module <GHC-TypeList.html>`.
For instance, we might use this interface to provide a more useful error
message for applications of ``show`` on unsaturated functions like this, ::
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
import GHC.TypeLits
instance TypeError (Text "Cannot 'Show' functions." :$$:
Text "Perhaps there is a missing argument?")
=> Show (a -> b) where
showsPrec = error "unreachable"
main = print negate
Which will produce the following compile-time error,
.. code-block:: none
Test.hs:12:8: error:
• Cannot 'Show' functions.
Perhaps there is a missing argument?
• In the expression: print negate
In an equation for ‘main’: main = print negate
.. _defer-type-errors:
Deferring type errors to runtime
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment