7.12. Special built-in functions

GHC has a few built-in funcions with special behaviour, described in this section. All are exported by GHC.Exts.

7.12.1. The inline function

The inline function is somewhat experimental.

  inline :: a -> a

The call (inline f) arranges that f is inlined, regardless of its size. More precisely, the call (inline f) rewrites to the right-hand side of f's definition. This allows the programmer to control inlining from a particular call site rather than the definition site of the function (c.f. INLINE pragmas Section 7.10.3, “INLINE and NOINLINE pragmas”).

This inlining occurs regardless of the argument to the call or the size of f's definition; it is unconditional. The main caveat is that f's definition must be visible to the compiler. That is, f must be let-bound in the current scope. If no inlining takes place, the inline function expands to the identity function in Phase zero; so its use imposes no overhead.

If the function is defined in another module, GHC only exposes its inlining in the interface file if the function is sufficiently small that it might be inlined by the automatic mechanism. There is currently no way to tell GHC to expose arbitrarily-large functions in the interface file. (This shortcoming is something that could be fixed, with some kind of pragma.)

7.12.2. The lazy function

The lazy function restrains strictness analysis a little:

  lazy :: a -> a

The call (lazy e) means the same as e, but lazy has a magical property so far as strictness analysis is concerned: it is lazy in its first argument, even though its semantics is strict. After strictness analysis has run, calls to lazy are inlined to be the identity function.

This behaviour is occasionally useful when controlling evaluation order. Notably, lazy is used in the library definition of Control.Parallel.par:

  par :: a -> b -> b
  par x y = case (par# x) of { _ -> lazy y }

If lazy were not lazy, par would look strict in y which would defeat the whole purpose of par.

7.12.3. The unsafeCoerce# function

The function unsafeCoerce# allows you to side-step the typechecker entirely. It has type

  unsafeCoerce# :: a -> b

That is, it allows you to coerce any type into any other type. If you use this function, you had better get it right, otherwise segmentation faults await. It is generally used when you want to write a program that you know is well-typed, but where Haskell's type system is not expressive enough to prove that it is well typed.