Bytestring map/zipWith rationale
Hello all, Something's always bothered me about map and zipWith for ByteString. Why is it map :: (Word8 -> Word8) -> ByteString -> ByteString but zipWith :: (Word8 -> Word8 -> a) -> ByteString -> ByteString -> [a] ? Obviously they can be transformed into each other with pack/unpack, and as I understand it, the compiler performs sufficient optimizations so that there's no performance hit to doing things like (pack $ zipWith xor a b), but it still seems inconsistent. Is there a deep reason for this? -- Scott Lawrence Linux baidar 3.10.9-1-ARCH #1 SMP PREEMPT Wed Aug 21 13:49:35 CEST 2013 x86_64 GNU/Linux
On Thu, Sep 12, 2013 at 09:21:20AM -0400, Scott Lawrence wrote:
Something's always bothered me about map and zipWith for ByteString. Why is it
map :: (Word8 -> Word8) -> ByteString -> ByteString
but
zipWith :: (Word8 -> Word8 -> a) -> ByteString -> ByteString -> [a]
Well, what if you wanted to zipWith a function of type "Word8 -> Word8 -> Foo" instead of "Word8 -> Word8 -> Word8"? Tom
On Thu, 12 Sep 2013 18:24:24 +0400, Tom Ellis <tom-lists-haskell-cafe-2013@jaguarpaw.co.uk> wrote:
On Thu, Sep 12, 2013 at 09:21:20AM -0400, Scott Lawrence wrote:
Something's always bothered me about map and zipWith for ByteString. Why is it
map :: (Word8 -> Word8) -> ByteString -> ByteString
but
zipWith :: (Word8 -> Word8 -> a) -> ByteString -> ByteString -> [a]
Well, what if you wanted to zipWith a function of type "Word8 -> Word8 -> Foo" instead of "Word8 -> Word8 -> Word8"?
Then why doesn’t map take “Word8 -> a”, but only “Word8 -> Word8”?
On Thu, 12 Sep 2013, Tom Ellis wrote:
On Thu, Sep 12, 2013 at 09:21:20AM -0400, Scott Lawrence wrote:
Something's always bothered me about map and zipWith for ByteString. Why is it
map :: (Word8 -> Word8) -> ByteString -> ByteString
but
zipWith :: (Word8 -> Word8 -> a) -> ByteString -> ByteString -> [a]
Well, what if you wanted to zipWith a function of type "Word8 -> Word8 -> Foo" instead of "Word8 -> Word8 -> Word8"?
Then I would do what I do with map, and call `unpack` first. Either of the two options is usable: map :: (Word8 -> Word8) -> ByteString -> ByteString zipWith :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString -> ByteString (or) map :: (Word8 -> a) -> ByteString -> [a] zipWith :: (Word8 -> Word8 -> a) -> ByteString -> ByteString -> [a] I just don't understand why we have one from each. -- Scott Lawrence
Scott: benchmark the two and you'll see why we have both :-) On Thursday, September 12, 2013, Scott Lawrence wrote:
On Thu, 12 Sep 2013, Tom Ellis wrote:
On Thu, Sep 12, 2013 at 09:21:20AM -0400, Scott Lawrence wrote:
Something's always bothered me about map and zipWith for ByteString. Why is it
map :: (Word8 -> Word8) -> ByteString -> ByteString
but
zipWith :: (Word8 -> Word8 -> a) -> ByteString -> ByteString -> [a]
Well, what if you wanted to zipWith a function of type "Word8 -> Word8 -> Foo" instead of "Word8 -> Word8 -> Word8"?
Then I would do what I do with map, and call `unpack` first.
Either of the two options is usable:
map :: (Word8 -> Word8) -> ByteString -> ByteString zipWith :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString -> ByteString (or) map :: (Word8 -> a) -> ByteString -> [a] zipWith :: (Word8 -> Word8 -> a) -> ByteString -> ByteString -> [a]
I just don't understand why we have one from each.
-- Scott Lawrence ______________________________**_________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/**mailman/listinfo/haskell-cafe<http://www.haskell.org/mailman/listinfo/haskell-cafe>
Carter: we don't have both. We have one function from each category. My guess is nobody's ever really needed a really fast zipWith :: (Word8->Word8->Word8) -> ByteString -> ByteString -> ByteString; that's the only reason I can think of for its omission. On Thu, Sep 12, 2013 at 10:45 AM, Carter Schonwald < carter.schonwald@gmail.com> wrote:
Scott: benchmark the two and you'll see why we have both :-)
On Thursday, September 12, 2013, Scott Lawrence wrote:
On Thu, 12 Sep 2013, Tom Ellis wrote:
On Thu, Sep 12, 2013 at 09:21:20AM -0400, Scott Lawrence wrote:
Something's always bothered me about map and zipWith for ByteString. Why is it
map :: (Word8 -> Word8) -> ByteString -> ByteString
but
zipWith :: (Word8 -> Word8 -> a) -> ByteString -> ByteString -> [a]
Well, what if you wanted to zipWith a function of type "Word8 -> Word8 -> Foo" instead of "Word8 -> Word8 -> Word8"?
Then I would do what I do with map, and call `unpack` first.
Either of the two options is usable:
map :: (Word8 -> Word8) -> ByteString -> ByteString zipWith :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString -> ByteString (or) map :: (Word8 -> a) -> ByteString -> [a] zipWith :: (Word8 -> Word8 -> a) -> ByteString -> ByteString -> [a]
I just don't understand why we have one from each.
-- Scott Lawrence ______________________________**_________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/**mailman/listinfo/haskell-cafe<http://www.haskell.org/mailman/listinfo/haskell-cafe>
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
I did use that a couple of times (`xor`ing 2 ByteStrings together), and was surprised by the omission back then, but IIRC (can't validate now), there's a specialised zipWith (as proposed) in the module (with some other name, obviously), which is not exported, but used when you 'pack' the result of 'zipWith' when the result is '[Word8]'... You might want to look into that. Nicolas On Sep 12, 2013 8:11 PM, "John Lato" <jwlato@gmail.com> wrote:
Carter: we don't have both. We have one function from each category. My guess is nobody's ever really needed a really fast zipWith :: (Word8->Word8->Word8) -> ByteString -> ByteString -> ByteString; that's the only reason I can think of for its omission.
On Thu, Sep 12, 2013 at 10:45 AM, Carter Schonwald < carter.schonwald@gmail.com> wrote:
Scott: benchmark the two and you'll see why we have both :-)
On Thursday, September 12, 2013, Scott Lawrence wrote:
On Thu, 12 Sep 2013, Tom Ellis wrote:
On Thu, Sep 12, 2013 at 09:21:20AM -0400, Scott Lawrence wrote:
Something's always bothered me about map and zipWith for ByteString. Why is it
map :: (Word8 -> Word8) -> ByteString -> ByteString
but
zipWith :: (Word8 -> Word8 -> a) -> ByteString -> ByteString -> [a]
Well, what if you wanted to zipWith a function of type "Word8 -> Word8 -> Foo" instead of "Word8 -> Word8 -> Word8"?
Then I would do what I do with map, and call `unpack` first.
Either of the two options is usable:
map :: (Word8 -> Word8) -> ByteString -> ByteString zipWith :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString -> ByteString (or) map :: (Word8 -> a) -> ByteString -> [a] zipWith :: (Word8 -> Word8 -> a) -> ByteString -> ByteString -> [a]
I just don't understand why we have one from each.
-- Scott Lawrence ______________________________**_________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/**mailman/listinfo/haskell-cafe<http://www.haskell.org/mailman/listinfo/haskell-cafe>
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
On Thu, Sep 12, 2013 at 12:44 PM, Nicolas Trangez <nicolas@incubaid.com> wrote:
I did use that a couple of times (`xor`ing 2 ByteStrings together), and was surprised by the omission back then, but IIRC (can't validate now), there's a specialised zipWith (as proposed) in the module (with some other name, obviously), which is not exported, but used when you 'pack' the result of 'zipWith' when the result is '[Word8]'... You might want to look into that.
This is correct - there is a RULES pragma that rewrites `pack (zipWith f)` into a more efficient `zipWith'` function of the type desired (see the bytestring package). I was very concerned about this when writing lots of bytestring xor code for crypto-api and was pleased to find that, if the syntactic form matches, things get optimized as you desire. Thomas
Nicolas
On Sep 12, 2013 8:11 PM, "John Lato" <jwlato@gmail.com> wrote:
Carter: we don't have both. We have one function from each category. My guess is nobody's ever really needed a really fast zipWith :: (Word8->Word8->Word8) -> ByteString -> ByteString -> ByteString; that's the only reason I can think of for its omission.
On Thu, Sep 12, 2013 at 10:45 AM, Carter Schonwald <carter.schonwald@gmail.com> wrote:
Scott: benchmark the two and you'll see why we have both :-)
On Thursday, September 12, 2013, Scott Lawrence wrote:
On Thu, 12 Sep 2013, Tom Ellis wrote:
On Thu, Sep 12, 2013 at 09:21:20AM -0400, Scott Lawrence wrote:
Something's always bothered me about map and zipWith for ByteString. Why is it
map :: (Word8 -> Word8) -> ByteString -> ByteString
but
zipWith :: (Word8 -> Word8 -> a) -> ByteString -> ByteString -> [a]
Well, what if you wanted to zipWith a function of type "Word8 -> Word8 -> Foo" instead of "Word8 -> Word8 -> Word8"?
Then I would do what I do with map, and call `unpack` first.
Either of the two options is usable:
map :: (Word8 -> Word8) -> ByteString -> ByteString zipWith :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString -> ByteString (or) map :: (Word8 -> a) -> ByteString -> [a] zipWith :: (Word8 -> Word8 -> a) -> ByteString -> ByteString -> [a]
I just don't understand why we have one from each.
-- Scott Lawrence _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
participants (7)
-
Artyom Kazak -
Carter Schonwald -
John Lato -
Nicolas Trangez -
Scott Lawrence -
Thomas DuBuisson -
Tom Ellis