Daniil Iaitskov
Daniil Iaitskov

Reputation: 6039

How to operate with unboxed types in Haskell

There is unboxed types GHC for Int, Float, etc. I know about code built on them is running with less overhead, but I don't see a way how to input and output data to/from a function based on unboxed Int i.e.

GHC.Exts defines functions (+#) and (*#), but I cannot find function boxing/unboxy

  readInt:: String -> Int#
  showInt:: Int# -> String

  boxInt :: Int# -> Int
  unboxInt :: Int -> Int#

instance Show Int# and instance Read Int# cannot exist because show and read polymorphic.

Without these function how could I integrated optimized code block on unboxed types with the rest of application?

Upvotes: 3

Views: 795

Answers (2)

leftaroundabout
leftaroundabout

Reputation: 120711

I know about code built on them is running with less overhead

Though this is true in a sense, it's nothing you should normally worry about. GHC tries very hard to optimise away the boxes of built-in types, and I'd expect that it manages to do it well in most cases where you could do that manually as well.

In practice, what you should be more careful about is to ensure

  • that it actually sees the concrete Int or Float type for which it knows the unboxed form. In particular, this does not work for polymorphic functions (polymorphism generally relies on the boxes, like it does in OO languages).
    If you want a function to be polymorphic and still run fast with the primitive types, make sure you add a SPECIALIZE annotation and/or rewrite rules.
  • that laziness doesn't get in the way. Unboxed types are always strict, so strictness annotations can make it a lot easier for GHC to remove the boxes.

And of course profile your code.

Only if you're really sure you want it (e.g. to ensure that the boxes won't re-appear when a new GHC that optimises differently), or maybe if you'd like to get SIMD instructions in, should you actually do manual accesses to unboxed primitive types.

Upvotes: 5

HTNW
HTNW

Reputation: 29193

Int, Float, etc. are just data types in GHC:

data Int = I# Int#
data Float = F# Float#
-- etc.

The constructors are only exported by GHC.Exts. Import it and use the constructors to convert:

{-# LANGUAGE MagicHash #-}

import GHC.Exts

main = do I# x <- readLn
          I# y <- readLn
          print (I# (x +# y))

Upvotes: 5

Related Questions