Magic hash
When you enable the MagicHash
GHC extension, two things change:
- The identifier naming rules are modified slightly so that names ending with one or more hash (
#
) characters are valid identifiers. Normally this wouldn’t be allowed. See identifiers and operators for the full details of what constitutes a valid name for something in Haskell. - You can now write unlifted literals such as
3#
. We discuss this further below.
Given how little this extension actually does, the choice to name it “magic hash” was perhaps a bit overdramatic.
When to enable MagicHash
Only enable the MagicHash
extension if you need it because you’re working with the primitives found in GHC.Exts
.
You technically can apply a hash suffix to the names of your own types and variables if you really want to:
λ> :set -XMagicHash
λ> data Person# = Person# { name# :: String, age# :: Natural }
But this is ill-advised. It is strongly conventional for the hash suffix to be applied only to unlifted types (types that have kind #
). See primitives, levity, and boxing for more a lengthier discussion of this convention.
Hashes in operators are normal
Note that MagicHash
only affects the rules for what constitutes a valid identifier name. You do not need an extension to have operator symbols that contain a hash. See identifiers and operators for a discussion on the difference between identifiers and operator symbols. That is always permissible.
λ> a # b = a^2 + b^2
λ> a ## b = a^3 + b^3
λ> 3 # 4
25
λ> 3 ## 4
91
Here are some examples of ordinary, non-weird examples of hash operators:
- The
diagrams
library(Diagrams.Util.#)
defines(#)
as a synonym for($)
with a different fixity. - The
lens
library(Control.Lens.Operators.#)
also defines an operator named(#)
.
Using those functions does not require a language extension because they are operator symbols, not identifiers.
Unlifted literals
Unlifted literals look like regular literals, but with one or two #
characters at the end.
λ> :type 3#
3# :: GHC.Prim.Int#
λ> :type 3##
3## :: GHC.Prim.Word#
λ> :type 3.2#
3.2# :: GHC.Prim.Float#
λ> :type 3.2##
3.2## :: GHC.Prim.Double#
λ> :type 'x'#
'x'# :: GHC.Prim.Char#
λ> :type "xyz"#
"xyz"# :: GHC.Prim.Addr#