
#10744: Allow oneShot to work with unboxed types -------------------------------------+------------------------------------- Reporter: akio | Owner: Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.2 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by akio): I use it in the fast-builder package [1], which aims to be a ByteString builder implementation that is significantly faster than the standard one. The main Builder type looks like this {{{#!hs type Builder = DataSink -> State -> State data DataSink = -- abstract data State = -- abstract -- | Builder concatenation. (<>) :: Builder -> Builder -> Builder a <> b = \sink s = b sink (a sink s) -- | Primitive builder. int :: Int -> Builder int = -- implementation omitted. }}} As an example, the user may write code like this to serialize a list of Ints: {{{#!hs serialize :: [Int] -> Builder serialize list = int (length list) <> foldr (<>) mempty (map int list) }}} For `serialize` to work efficiently, I really want it to have the arity of 3. However, simply inlining `int` and `(<>)` only gives {{{#!hs serialize = \list -> let len = length list in \sink s -> ... }}} So it gets arity 1, which means it has to allocate a lambda and then call it. By default GHC doesn't eta-expand `serialize` because it wants to avoid evaluating `length` multiple times. However, I want GHC to produce better code in the assumption that the resulting Builder will be used at most once, because using the same Builder multiple times is usually a bad idea anyway (you should instead turn it into a ByteString and use that ByteString multiple times). I express this preference by inserting calls to `oneShot` into the definitions of `(<>)`, `int`, etc. The current type of `oneShot` means `State` has to be a lifted type. Ideally I'd like to use something like `(# Addr#, Addr#, State# RealWorld #)`. [1]: http://hackage.haskell.org/package/fast-builder -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10744#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler