Some notes on using unboxed types in Haskell, and in particular, notes on creating a boxed wrapper for the integer-gmp library function integerLog2# :: Integer -> Int#
which returns an unboxed type.
{-# LANGUAGE MagicHash #-}
import GHC.Exts(Int(I#));
import GHC.Integer.Logarithms(integerLog2#);
integerLog2 :: Integer -> Int;
integerLog2 i = if i < 1
then error "must be positive"
-- because integerLog2# does no bounds checking
else I# (integerLog2# i);
The pragma MagicHash prevents GHC from interpreting the hash symbol as an operator. Without it, one gets error messages like this:
parse error on input `#'
not in scope: `#'
It would be nice if GHC emitted a suggestion of MagicHash on errors like this.
The constructor I# is findable using Hoogle, searching for Int#->Int.
One must use parentheses around the argument to I#. The standard trick of removing parentheses with the dollar sign results in an error:
bad1 i = I# $ integerLog2# i;
Couldn't match kind `*' with `#'
When matching types
r0 :: *
GHC.Prim.Int# :: #
Using the composition operator in point-free style fails similarly:
bad2 = I# . integerLog2#;
Couldn't match kind `*' with `#'
When matching types
b0 :: *
GHC.Prim.Int# :: #
Expected type: b0 -> Int
Actual type: GHC.Prim.Int# -> Int
In the first argument of `(.)', namely `I#'
Unboxed types are a different "kind", the # kind, than boxed types, which are a * kind.
No comments :
Post a Comment