+section "Etc"
+ {Miscellaneous built-ins}
+------------------------------------------------------------------------
+
+pseudoop "seq"
+ a -> b -> b
+ { Evaluates its first argument to head normal form, and then returns its second
+ argument as the result. }
+
+pseudoop "inline"
+ a -> a
+ { The call {\tt (inline f)} arranges that f is inlined, regardless of its size.
+ More precisely, the call {\tt (inline f)} rewrites to the right-hand side of
+ {\tt 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.
+ {\tt INLINE} pragmas in User's Guide, Section 7.10.3, "INLINE and NOINLINE
+ pragmas").
+
+ This inlining occurs regardless of the argument to the call or the size of
+ {\tt f}'s definition; it is unconditional. The main caveat is that {\tt f}'s
+ definition must be visible to the compiler. That is, {\tt f} must be
+ {\tt let}-bound in the current scope. If no inlining takes place, the
+ {\tt 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.) }
+
+pseudoop "lazy"
+ a -> a
+ { The {\tt lazy} function restrains strictness analysis a little. The call
+ {\tt (lazy e)} means the same as {\tt e}, but {\tt 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 {\tt lazy} are inlined to be the identity function.
+
+ This behaviour is occasionally useful when controlling evaluation order.
+ Notably, {\tt lazy} is used in the library definition of {\tt Control.Parallel.par}:
+
+ {\tt par :: a -> b -> b}
+
+ {\tt par x y = case (par\# x) of \_ -> lazy y}
+
+ If {\tt lazy} were not lazy, {\tt par} would look strict in {\tt y} which
+ would defeat the whole purpose of {\tt par}.
+
+ Like {\tt seq}, the argument of {\tt lazy} can have an unboxed type. }
+
+primtype Any a
+ { The type constructor {\tt Any} is type to which you can unsafely coerce any
+ lifted type, and back.
+
+ * It is lifted, and hence represented by a pointer
+
+ * It does not claim to be a {\it data} type, and that's important for
+ the code generator, because the code gen may {\it enter} a data value
+ but never enters a function value.
+
+ It's also used to instantiate un-constrained type variables after type
+ checking. For example
+
+ {\tt length Any []}
+
+ Annoyingly, we sometimes need {\tt Any}s of other kinds, such as {\tt (* -> *)} etc.
+ This is a bit like tuples. We define a couple of useful ones here,
+ and make others up on the fly. If any of these others end up being exported
+ into interface files, we'll get a crash; at least until we add interface-file
+ syntax to support them. }
+
+pseudoop "unsafeCoerce#"
+ a -> b
+ { The function {\tt unsafeCoerce\#} allows you to side-step the typechecker entirely. 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.
+
+ The argument to {\tt unsafeCoerce\#} can have unboxed types, although extremely bad
+ things will happen if you coerce a boxed type to an unboxed type. }