haskellghcjs

GHCJS Text Data Constructor


I am using nix with reflex platform to compile haskell to javascript with GHCJS 8.0.1. I have written some functions that rely on an internal module in the text library: Data.Text.Internal. The only thing I need from this is the data constructor for Text:

data Text = Text
  {-# UNPACK #-} !A.Array -- payload (Word16 elements)
  {-# UNPACK #-} !Int     -- offset (units of Word16, not Char)
  {-# UNPACK #-} !Int     -- length (units of Word16, not Char)

However, when I try to compile code that uses this data constructor with GHCJS, it fails. The error message makes it clear that somehow, somewhere, the data constructor for Text has been replaced by:

newtype Text = Text JSString

I understand that I can put #ifdefs around blocks of code to work around this. However, I cannot figure out how this data constructor replacement has been accomplished. This is not mentioned anywhere in ghcjs-shims. It isn't mentioned is ghcjs either. Even weirder is that ghcjs-base has functions that use the normal data constructor for Text. I would appreciate if anyone could point me to the source of this replacement.

EDIT: This is not relevant to the question, but the reason I need to use the internals of Text is to efficiently encode things like IPv4 addresses and MAC addresses. In my the benchmarks I included with a previous question, I found that the fastest IPv4 encoding using the public API of text took around 450ns. Using the internals (and writing to a mutable array directly), I can do this in around 35ns, which is at least at 10x improvement in performance.

EDIT 2: Something else I just remembered (which is possibly relevant to the question) is that in another place in my code, I had used hexadecimal from Data.Text.Lazy.Builder.Int. However, with ghcjs, this function isn't exported by this module. I would be glad to contribute it upstream somewhere, but since I don't understand how all of the modules in text are getting shimmed out, I don't know where the appropriate upstream for this is. I would appreciate if someone could point me to the specific file where this is accomplished.


Solution

  • It looks like you might be using reflex-platform. We recently integrated a change that uses JSString for Text rather than the usual implementation; that's because JSString is dramatically faster and uses a lot less memory than the pure-Haskell Text implementation.

    If this is what you're running into, I'd encourage you to stick with JSString unless you're quite unconcerned about performance. However, if you'd like to disable this optimization, I think it should work to just comment out this block and then re-enter your try-reflex/work-on/nix-shell.