This question arises from a challenge Brent Yorgey posed at OPLSS: write a function f :: (Int -> Int) -> Bool
that distinguishes f
seq
cannot be implemented in Haskell. Instead, it is a primitive "hook" into evaluation to weak-head normal form in whatever runtime your Haskell is running on. E.g. on GHC it is compiled to a case
in GHC Core, which triggers evaluation to the outermost constructor.
Since it can't be implemented in pure Haskell, it is defined (in GHC) as a primop:
pseudoop "seq"
a -> b -> b
{ Evaluates its first argument to head normal form, and then returns its second
argument as the result. }
Since functions don't have a normal form, seq
halts evaluation once it reaches one.
Magically available to the compiler. The same goes for other primitives like par
or unsafeCoerce
, the RealWorld
token, forkOn
and so on. All the useful stuff.
There is a more higher-level description of STG-machine in How to make a fast curry: push/enter vs eval/apply
Figure 2 contains rule CASEANY that works for functions. In this paper "is a value" proposition means either:
Unboxed values, including literals are treated specially, more information can be found in Unboxed values as first class citizens
All these are implementation details and are hidden inside compiler (GHC). Haskell's case expression doesn't force it's scrutineer, only pattern-matching and seq do.