
Howdy, I'd like to announce a first version of base91 http://hackage.haskell.org/package/base91, a Haskell package to enable the encoding and decoding of data in Base91 format, as documented in its specification http://base91.sourceforge.net. The main benefits of said scheme are a good reduction in overhead (from 31% up to 58%) when compared to Base64 due to the clever use of two printable ASCII characters (consuming 16 bits) to encode 13 arbitrary bits, as well as neither need for nor ambiguity over padding or alphabets. It includes support for... - Plain Strings (module Codec.Binary.Base91.String) - Data.ByteString (module Codec.Binary.Base91.ByteString) - Data.Text (module Codec.Binary.Base91.Text) - The latter two combined (module Codec.Binary.Base91.Efficient) - Data.ByteString.Lazy (module Codec.Binary.Base91.ByteString.Lazy) - Data.Text.Lazy (module Codec.Binary.Base91.Text.Lazy) - The latter two combined (module Codec.Binary.Base91.Efficient.Lazy) ...which are all just concretely typed versions of the generic implementation in Codec.Binary.Base91. I had fun exploring some of the latest GHC extensions, as evidenced by Codec.Binary.Base91.Control, which relies on a certain amount of type trickery to reconcile the incongruence between monomorphic containers and the standard type classes. Anyway, suggestions are very welcome. In particular, I'm interested in: 1. Whether the generic decode and encode signatures can be simplified or improved elsehow. 2. Whether there already exist classes similar in purpose to Applicative' and Foldable'. 3. Whether it makes sense to offer decode and encode variants that use lazy (left) folds--currently folding is always strict, even with lazy types. (Testing comes nearly free courtesy of QuickCheck and the identity property of decode . encode, plus a couple of concrete examples. Please open an issue or otherwise let me know if you find a bug.) Thank you, Alvaro http://alva.ro

Suggestion: I notice that you are using indexing into a list as a lookup
table, you might want to switch to a vector + unsafe reads in the efficient
version
Ben
On Fri, 10 Jul 2015 at 01:24 Alvaro J. Genial
Howdy,
I'd like to announce a first version of base91 http://hackage.haskell.org/package/base91, a Haskell package to enable the encoding and decoding of data in Base91 format, as documented in its specification http://base91.sourceforge.net. The main benefits of said scheme are a good reduction in overhead (from 31% up to 58%) when compared to Base64 due to the clever use of two printable ASCII characters (consuming 16 bits) to encode 13 arbitrary bits, as well as neither need for nor ambiguity over padding or alphabets.
It includes support for...
- Plain Strings (module Codec.Binary.Base91.String) - Data.ByteString (module Codec.Binary.Base91.ByteString) - Data.Text (module Codec.Binary.Base91.Text) - The latter two combined (module Codec.Binary.Base91.Efficient) - Data.ByteString.Lazy (module Codec.Binary.Base91.ByteString.Lazy) - Data.Text.Lazy (module Codec.Binary.Base91.Text.Lazy) - The latter two combined (module Codec.Binary.Base91.Efficient.Lazy)
...which are all just concretely typed versions of the generic implementation in Codec.Binary.Base91.
I had fun exploring some of the latest GHC extensions, as evidenced by Codec.Binary.Base91.Control, which relies on a certain amount of type trickery to reconcile the incongruence between monomorphic containers and the standard type classes.
Anyway, suggestions are very welcome. In particular, I'm interested in:
1. Whether the generic decode and encode signatures can be simplified or improved elsehow. 2. Whether there already exist classes similar in purpose to Applicative' and Foldable'. 3. Whether it makes sense to offer decode and encode variants that use lazy (left) folds--currently folding is always strict, even with lazy types.
(Testing comes nearly free courtesy of QuickCheck and the identity property of decode . encode, plus a couple of concrete examples. Please open an issue or otherwise let me know if you find a bug.)
Thank you,
Alvaro http://alva.ro
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe

Take a look at mono-traversable
https://hackage.haskell.org/package/mono-traversable. pure' is singleton
and Foldable' is MonoFoldable.
On Fri, Jul 10, 2015 at 1:23 AM, Alvaro J. Genial
Howdy,
I'd like to announce a first version of base91 http://hackage.haskell.org/package/base91, a Haskell package to enable the encoding and decoding of data in Base91 format, as documented in its specification http://base91.sourceforge.net. The main benefits of said scheme are a good reduction in overhead (from 31% up to 58%) when compared to Base64 due to the clever use of two printable ASCII characters (consuming 16 bits) to encode 13 arbitrary bits, as well as neither need for nor ambiguity over padding or alphabets.
It includes support for...
- Plain Strings (module Codec.Binary.Base91.String) - Data.ByteString (module Codec.Binary.Base91.ByteString) - Data.Text (module Codec.Binary.Base91.Text) - The latter two combined (module Codec.Binary.Base91.Efficient) - Data.ByteString.Lazy (module Codec.Binary.Base91.ByteString.Lazy) - Data.Text.Lazy (module Codec.Binary.Base91.Text.Lazy) - The latter two combined (module Codec.Binary.Base91.Efficient.Lazy)
...which are all just concretely typed versions of the generic implementation in Codec.Binary.Base91.
I had fun exploring some of the latest GHC extensions, as evidenced by Codec.Binary.Base91.Control, which relies on a certain amount of type trickery to reconcile the incongruence between monomorphic containers and the standard type classes.
Anyway, suggestions are very welcome. In particular, I'm interested in:
1. Whether the generic decode and encode signatures can be simplified or improved elsehow. 2. Whether there already exist classes similar in purpose to Applicative' and Foldable'. 3. Whether it makes sense to offer decode and encode variants that use lazy (left) folds--currently folding is always strict, even with lazy types.
(Testing comes nearly free courtesy of QuickCheck and the identity property of decode . encode, plus a couple of concrete examples. Please open an issue or otherwise let me know if you find a bug.)
Thank you,
Alvaro http://alva.ro
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe

Actually Applicative' is MonoPointed
https://hackage.haskell.org/package/mono-traversable-0.9.2.1/docs/Data-MonoT...
.
On Fri, Jul 10, 2015 at 2:46 PM, Patrick Chilton
Take a look at mono-traversable https://hackage.haskell.org/package/mono-traversable. pure' is singleton and Foldable' is MonoFoldable.
On Fri, Jul 10, 2015 at 1:23 AM, Alvaro J. Genial
wrote: Howdy,
I'd like to announce a first version of base91 http://hackage.haskell.org/package/base91, a Haskell package to enable the encoding and decoding of data in Base91 format, as documented in its specification http://base91.sourceforge.net. The main benefits of said scheme are a good reduction in overhead (from 31% up to 58%) when compared to Base64 due to the clever use of two printable ASCII characters (consuming 16 bits) to encode 13 arbitrary bits, as well as neither need for nor ambiguity over padding or alphabets.
It includes support for...
- Plain Strings (module Codec.Binary.Base91.String) - Data.ByteString (module Codec.Binary.Base91.ByteString) - Data.Text (module Codec.Binary.Base91.Text) - The latter two combined (module Codec.Binary.Base91.Efficient) - Data.ByteString.Lazy (module Codec.Binary.Base91.ByteString.Lazy) - Data.Text.Lazy (module Codec.Binary.Base91.Text.Lazy) - The latter two combined (module Codec.Binary.Base91.Efficient.Lazy)
...which are all just concretely typed versions of the generic implementation in Codec.Binary.Base91.
I had fun exploring some of the latest GHC extensions, as evidenced by Codec.Binary.Base91.Control, which relies on a certain amount of type trickery to reconcile the incongruence between monomorphic containers and the standard type classes.
Anyway, suggestions are very welcome. In particular, I'm interested in:
1. Whether the generic decode and encode signatures can be simplified or improved elsehow. 2. Whether there already exist classes similar in purpose to Applicative' and Foldable'. 3. Whether it makes sense to offer decode and encode variants that use lazy (left) folds--currently folding is always strict, even with lazy types.
(Testing comes nearly free courtesy of QuickCheck and the identity property of decode . encode, plus a couple of concrete examples. Please open an issue or otherwise let me know if you find a bug.)
Thank you,
Alvaro http://alva.ro
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe

On Fri, Jul 10, 2015 at 9:46 AM, Patrick Chilton
Take a look at mono-traversable https://hackage.haskell.org/package/mono-traversable. pure' is singleton and Foldable' is MonoFoldable.
On Fri, Jul 10, 2015 at 9:47 AM, Patrick Chilton
Actually Applicative' is MonoPointed https://hackage.haskell.org/package/mono-traversable-0.9.2.1/docs/Data-MonoT... .
Thank you! Indeed, I was able to re-implement the library deferring to MonoFoldable and MonoPointed and then collapse the whole thing to a single module with two functions that automatically work with all suitable input and output types. In terms of the package (and since I'll be bumping the major version) I don't think the specialized modules are needed any more, since they're just a small subset of the combinatorial input/output space. Or is there a tangible benefit to users in providing more concretely typed versions for those (unusual?) cases where the return type is ambiguous? So, given: type Input i e = (MonoFoldable i, Element i ~ e) type Output o e = (MonoPointed o, Element o ~ e, Monoid o) encode :: forall i o. (Input i Word8, Output o Char) => i -> o decode :: forall i o. (Input i Char, Output o Word8) => i -> o Does including and exposing the following... encodeToString :: Input i Word8 => i -> [Char] decodeToBytes :: Input i Char => i -> [Word8] encodeBytes :: Output o Char => [Word8] -> o decodeString :: Output o Word8 => [Char] -> o encodeBytesToString :: [Word8] -> [Char] decodeStringToBytes :: [Char] -> [Word8] ...add any value, being trivially defined as equal to the generic version? (Plus, the explosion doubles with another dimension like lazy vs. strict.) I don't see much advantage over e.g. (encode ws :: String) for the first case. Thanks again, Alvaro http://alva.ro

Hi Alvaro,
Sorry about the late response, but is this overloading truly necessary?
`Text.unpack` isn't that much to type, and I'm not sure if the
benefits of overloading outweigh the cognitive load. `String` and
`[Word8]` are rare in production code, and not everyone uses (or is
aware of) mono-traversable.
As a data point, the base16-bytestring and base64-bytestring packages
only expose functions of type `ByteString -> ByteString`.
On Sat, Jul 11, 2015 at 7:11 AM, Alvaro J. Genial
On Fri, Jul 10, 2015 at 9:46 AM, Patrick Chilton
wrote: Take a look at mono-traversable. pure' is singleton and Foldable' is MonoFoldable.
On Fri, Jul 10, 2015 at 9:47 AM, Patrick Chilton
wrote: Actually Applicative' is MonoPointed.
Thank you! Indeed, I was able to re-implement the library deferring to MonoFoldable and MonoPointed and then collapse the whole thing to a single module with two functions that automatically work with all suitable input and output types.
In terms of the package (and since I'll be bumping the major version) I don't think the specialized modules are needed any more, since they're just a small subset of the combinatorial input/output space. Or is there a tangible benefit to users in providing more concretely typed versions for those (unusual?) cases where the return type is ambiguous? So, given:
type Input i e = (MonoFoldable i, Element i ~ e) type Output o e = (MonoPointed o, Element o ~ e, Monoid o)
encode :: forall i o. (Input i Word8, Output o Char) => i -> o decode :: forall i o. (Input i Char, Output o Word8) => i -> o
Does including and exposing the following...
encodeToString :: Input i Word8 => i -> [Char] decodeToBytes :: Input i Char => i -> [Word8] encodeBytes :: Output o Char => [Word8] -> o decodeString :: Output o Word8 => [Char] -> o encodeBytesToString :: [Word8] -> [Char] decodeStringToBytes :: [Char] -> [Word8]
...add any value, being trivially defined as equal to the generic version? (Plus, the explosion doubles with another dimension like lazy vs. strict.) I don't see much advantage over e.g. (encode ws :: String) for the first case.
Thanks again,
Alvaro
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
-- Chris Wong (https://lambda.xyz) "Humans find such fascinating ways to waste their time." -- Steven Universe
participants (4)
-
Alvaro J. Genial
-
Benjamin Edwards
-
Chris Wong
-
Patrick Chilton