5

There are standard (pure) map functions for ByteString and Text:

map :: (Word8 -> Word8) -> ByteString -> ByteString
map :: (Char -> Char) -> Text -> Text

but I'm missing their monadic/applicative counterparts:

traverse :: (Applicative f) => (Word8 -> f Word8) -> ByteString -> f ByteString
traverse :: (Applicative f) => (Char -> f Char) -> Text -> f Text

(If we have traverse we can define mapM f = unwrapMonad . traverse (WrapMonad . f).)

I tried looking through the packages, tried Hoogle, but I didn't find them. Did I overlook something? Or is there a reason why they're missing (like it's not possible/easy to define them efficiently)?

Petr
  • 62,528
  • 13
  • 153
  • 317
  • 2
    Out of curiosity, what do you need them for? – Mikhail Glushenkov Oct 18 '12 at 12:03
  • 2
    Not being the author of either package, my guess is that the definitions would be quite ugly. It would seem to involve a lot of interleaving `unsafePerformIO`. – John L Oct 18 '12 at 12:17
  • 1
    @MikhailGlushenkov I'm trying to make a few enhancements to the [ListLike](http://hackage.haskell.org/package/ListLike) package. In particular, monadic/applicative traversal over elements. Current implementation does it by converting the collection to a list and then folding `snoc` over it, which is very inefficient. – Petr Oct 18 '12 at 12:26
  • 1
    there are `ByteString.head` and `ByteString.tail` - if they are pointer operation underneath, traversing a ByteString with them may have decent performance. – Dmytro Sirenko Oct 18 '12 at 12:32
  • 1
    @EarlGray AFAIK there are pointer operations underneath. `head` and `tail` are enough for folding. But the problem with traversing is that it also needs to rebuild the structure with modified elements. – Petr Oct 18 '12 at 12:56

1 Answers1

2

Incidentally, you have exactly what you need in Edward Kmett's lens package; your desired traverse versions are simply Data.Bytestring.Lens.bytes and Data.Text.Lens.text.

Edit: To clarify, the above-mentioned functions are of (a generalization of) type SimpleTraversal c e (for (c ~ Bytestring, e ~ Word8) and (c ~ Text, e ~ Char), respectively), which is a type synonym for forall f. (Applicative f) => (e -> f e) -> c -> f c

Ptharien's Flame
  • 3,246
  • 20
  • 24
  • 1
    Thanks, the package looks quite interesting. Do you know how efficiently are those method implemented? Do they go to the `ByteString`'s or `Text`'s internals, or do they do something like `pack . traverse f . unpack`? – Petr Oct 18 '12 at 20:46
  • 2
    @PetrPudlák Looking at [the source](http://hackage.haskell.org/packages/archive/lens/3.0.4/doc/html/src/Data-ByteString-Strict-Lens.html), it seems that it's just `pack . map f . unpack ` – Mikhail Glushenkov Oct 19 '12 at 00:31