Re: Proposal: Add hasBitSize to Data.Bits.Bits

From: Edward Kmett
On Fri, Jul 27, 2012 at 3:42 PM, Ian Lynagh
wrote: On Fri, Jul 27, 2012 at 03:06:04PM -0400, Edward Kmett wrote:
There is currently no way to know whether or not calling Data.Bits.bitSizewill crash your program.
I propose extending the Bits class to include:
hasBitSize :: Bits b => b -> Bool
such that it returns False for Integer and True for the other instances
Would it be better to move bitSize into a separate class?
I don't think so. Ultimately, you should be able to know for every numeric type if it has a fixed or variable number of bits. In a perfect world 'd rather just have bitSize return a Maybe that way we don't have to truck with partial functions in the API.
However, the case for just adding hasBitSize is that it avoids breaking existing code.
Given that existing code using bitSize can already cause a crash when used with Integer or other infinite types, wouldn't it be better to break existing code so authors can fix (or at least examine) their use of bitSize? I'm in favor of changing the type of bitSize, although since none of my code uses that function it's an easy position for me to take. John L.

On 28.07.12 4:40 PM, John Lato wrote:
From: Edward Kmett
On Fri, Jul 27, 2012 at 3:42 PM, Ian Lynagh
wrote: On Fri, Jul 27, 2012 at 03:06:04PM -0400, Edward Kmett wrote:
There is currently no way to know whether or not calling Data.Bits.bitSizewill crash your program.
I propose extending the Bits class to include:
hasBitSize :: Bits b => b -> Bool
I'm in favor of changing the type of bitSize, although since none of my code uses that function it's an easy position for me to take.
+1. The Haskellish solution would let return bitSize a Maybe. -- Andreas Abel <>< Du bist der geliebte Mensch. Theoretical Computer Science, University of Munich Oettingenstr. 67, D-80538 Munich, GERMANY andreas.abel@ifi.lmu.de http://www2.tcs.ifi.lmu.de/~abel/

Don't add hasBitSize, add perhapsBitSize (or some other name) which returns
a Maybe, and then bitSize can be deprecated.
-- Lennart
On Sat, Jul 28, 2012 at 5:57 PM, Andreas Abel
On 28.07.12 4:40 PM, John Lato wrote:
From: Edward Kmett
On Fri, Jul 27, 2012 at 3:42 PM, Ian Lynagh
wrote: On Fri, Jul 27, 2012 at 03:06:04PM -0400, Edward Kmett wrote:
There is currently no way to know whether or not calling Data.Bits.bitSizewill crash your program.
I propose extending the Bits class to include:
hasBitSize :: Bits b => b -> Bool
I'm in favor of changing the type of bitSize, although since none of my code uses that function it's an easy position for me to take.
+1. The Haskellish solution would let return bitSize a Maybe.
-- Andreas Abel <>< Du bist der geliebte Mensch.
Theoretical Computer Science, University of Munich Oettingenstr. 67, D-80538 Munich, GERMANY
andreas.abel@ifi.lmu.de http://www2.tcs.ifi.lmu.de/~**abel/ http://www2.tcs.ifi.lmu.de/~abel/
______________________________**_________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/**mailman/listinfo/librarieshttp://www.haskell.org/mailman/listinfo/libraries

On Sat, Jul 28, 2012 at 11:57 AM, Andreas Abel
On 28.07.12 4:40 PM, John Lato wrote:
From: Edward Kmett
On Fri, Jul 27, 2012 at 3:42 PM, Ian Lynagh
wrote: On Fri, Jul 27, 2012 at 03:06:04PM -0400, Edward Kmett wrote:
There is currently no way to know whether or not calling Data.Bits.bitSizewill crash your program.
I propose extending the Bits class to include:
hasBitSize :: Bits b => b -> Bool
I'm in favor of changing the type of bitSize, although since none of my code uses that function it's an easy position for me to take.
+1. The Haskellish solution would let return bitSize a Maybe.
Is 'bitSize' a useful function to use monomorphically? It seems a waste and irritating to have it return Maybe if I'm not using Integer. Antoine

On Sat, Jul 28, 2012 at 5:33 PM, Antoine Latter
On Sat, Jul 28, 2012 at 11:57 AM, Andreas Abel
wrote: On 28.07.12 4:40 PM, John Lato wrote:
From: Edward Kmett
On Fri, Jul 27, 2012 at 3:42 PM, Ian Lynagh
wrote: On Fri, Jul 27, 2012 at 03:06:04PM -0400, Edward Kmett wrote:
There is currently no way to know whether or not calling Data.Bits.bitSizewill crash your program.
I propose extending the Bits class to include:
hasBitSize :: Bits b => b -> Bool
I'm in favor of changing the type of bitSize, although since none of my code uses that function it's an easy position for me to take.
+1. The Haskellish solution would let return bitSize a Maybe.
Is 'bitSize' a useful function to use monomorphically? It seems a waste and irritating to have it return Maybe if I'm not using Integer.
That is a great point. Most my uses of 'bitSize' are monomorphic and Maybe would just be silly. OTOH, I'd be more than happy to fix up any polymorphic code to include a new BitSize constraint. Thomas

On 29 July 2012 15:37, Thomas DuBuisson
Is 'bitSize' a useful function to use monomorphically? It seems a waste and irritating to have it return Maybe if I'm not using Integer.
That is a great point. Most my uses of 'bitSize' are monomorphic and Maybe would just be silly. OTOH, I'd be more than happy to fix up any polymorphic code to include a new BitSize constraint.
To make sure I understand this correctly: The current problem is that bitSize is a partial function *depending on the type* of its argument (currently it always returns _|_ for Integer, and is total for any other type). That does indeed seem like a Bad Idea. You propose to: 1. Remove "bitSize" from the Bits class. 2. Add a new class BitSize which only contains the "bitSize" method. Integer would not be an instance of this class. So, then: - I assume we want a deprecation cycle. How, will that work? - Do we have a formal definition of what bitSize means? E.g., could/should a (finite) ByteString be made an instance of this? / Thomas

On Sun, Jul 29, 2012 at 8:37 AM, Thomas Schilling
To make sure I understand this correctly:
The current problem is that bitSize is a partial function *depending on the type* of its argument (currently it always returns _|_ for Integer, and is total for any other type). That does indeed seem like a Bad Idea.
You propose to:
1. Remove "bitSize" from the Bits class. 2. Add a new class BitSize which only contains the "bitSize" method. Integer would not be an instance of this class.
Yes, that is the solution I would support.
So, then:
- I assume we want a deprecation cycle. How, will that work?
I don't have a good answer to this question. I'd support the change even without a normal deprecation cycle, but I'm more flexible than some.
- Do we have a formal definition of what bitSize means? E.g., could/should a (finite) ByteString be made an instance of this?
I think bitSize is already defined as to mean the number of bits used in the representation of the value. There are no padding bits and it does not depend on the value (so passing "undefined :: T" should work for all instances). This means ByteString could not be a reasonable instance. If, OTOH, we had reifyable type level numerics and a ByteString-like type that encoded it's length in the type then this could be an instance. -The other Thomas

On Sun, Jul 29, 2012 at 10:37 AM, Thomas Schilling
On 29 July 2012 15:37, Thomas DuBuisson
wrote: Is 'bitSize' a useful function to use monomorphically? It seems a waste and irritating to have it return Maybe if I'm not using Integer.
That is a great point. Most my uses of 'bitSize' are monomorphic and Maybe would just be silly. OTOH, I'd be more than happy to fix up any polymorphic code to include a new BitSize constraint.
To make sure I understand this correctly:
The current problem is that bitSize is a partial function *depending on the type* of its argument (currently it always returns _|_ for Integer, and is total for any other type). That does indeed seem like a Bad Idea.
You propose to:
1. Remove "bitSize" from the Bits class. 2. Add a new class BitSize which only contains the "bitSize" method. Integer would not be an instance of this class.
The downside to this proposal is that the requester (Edward) actually wants a function of type "a -> Maybe Int", so his polymorphic function can handle both infinite bit-types and finite bit-types. With the new class, Edward could write: class BitTraversable i where traverseBits :: <sometype> instance (BitSize i) => BitTraversable i where traverseBits = <something> instance BitTraversable Integer where traverseBits = <something else> Antoine

On Sun, Jul 29, 2012 at 11:37 AM, Antoine Latter
The downside to this proposal is that the requester (Edward) actually wants a function of type "a -> Maybe Int", so his polymorphic function can handle both infinite bit-types and finite bit-types.
With the new class, Edward could write:
class BitTraversable i where traverseBits :: <sometype>
instance (BitSize i) => BitTraversable i where traverseBits = <something>
instance BitTraversable Integer where traverseBits = <something else>
I should add that this approach looks like it would require OverlappingInstances. Antoine

On Sun, Jul 29, 2012 at 12:38 PM, Antoine Latter
On Sun, Jul 29, 2012 at 11:37 AM, Antoine Latter
wrote: The downside to this proposal is that the requester (Edward) actually wants a function of type "a -> Maybe Int", so his polymorphic function can handle both infinite bit-types and finite bit-types.
With the new class, Edward could write:
class BitTraversable i where traverseBits :: <sometype>
instance (BitSize i) => BitTraversable i where traverseBits = <something>
instance BitTraversable Integer where traverseBits = <something else>
I should add that this approach looks like it would require OverlappingInstances.
Correct. This is not a viable solution for the problem, also it precludes the existance of support for someone else's Natural number type, etc. Every type that is currently an instance of Bits is either of a fixed size or potentially infinite. Changing bitSize to return a Maybe a works. Making a separate BitSize class simply forces me to do exactly what I'm doing right now, which is ignore it and manually probe. I'm a strong -1 vote to any solution that splits BitSize out into a separate class. -Edward

On Mon, 13 Aug 2012, Edward Kmett wrote:
Correct. This is not a viable solution for the problem, also it precludes the existance of support for someone else's Natural number type, etc.
Every type that is currently an instance of Bits is either of a fixed size or potentially infinite.
Changing bitSize to return a Maybe a works. Making a separate BitSize class simply forces me to do exactly what I'm doing right now, which is ignore it and manually probe.
How about two versions of 'bitSize' - one with Maybe return type in the Bits class and one without Maybe in a FixedBitSize subclass?

That would work perfectly.
Sent from my iPhone
On Aug 13, 2012, at 5:48 PM, Henning Thielemann
On Mon, 13 Aug 2012, Edward Kmett wrote:
Correct. This is not a viable solution for the problem, also it precludes the existance of support for someone else's Natural number type, etc. Every type that is currently an instance of Bits is either of a fixed size or potentially infinite. Changing bitSize to return a Maybe a works. Making a separate BitSize class simply forces me to do exactly what I'm doing right now, which is ignore it and manually probe.
How about two versions of 'bitSize' - one with Maybe return type in the Bits class and one without Maybe in a FixedBitSize subclass?

On Mon, Aug 13, 2012 at 2:48 PM, Henning Thielemann
How about two versions of 'bitSize' - one with Maybe return type in the Bits class and one without Maybe in a FixedBitSize subclass?
Is this worth breaking existing users of bitSize over? If anything it seems more worthwhile to throw out Integer from the Bits class and declare Bits to be for fixed sized entities.

On Mon, 13 Aug 2012, Johan Tibell wrote:
On Mon, Aug 13, 2012 at 2:48 PM, Henning Thielemann
wrote: How about two versions of 'bitSize' - one with Maybe return type in the Bits class and one without Maybe in a FixedBitSize subclass?
Is this worth breaking existing users of bitSize over?
If the method of 'FixedBitSize' is named 'bitSize' then only the type signature will be affected (FixedBitSize constraint instead of Bits). Although I don't know whether this is a good solution.
If anything it seems more worthwhile to throw out Integer from the Bits class and declare Bits to be for fixed sized entities.

On Mon, Aug 13, 2012 at 3:19 PM, Henning Thielemann
On Mon, 13 Aug 2012, Johan Tibell wrote:
On Mon, Aug 13, 2012 at 2:48 PM, Henning Thielemann
wrote: How about two versions of 'bitSize' - one with Maybe return type in the Bits class and one without Maybe in a FixedBitSize subclass?
Is this worth breaking existing users of bitSize over?
If the method of 'FixedBitSize' is named 'bitSize' then only the type signature will be affected (FixedBitSize constraint instead of Bits). Although I don't know whether this is a good solution.
Imports will have to be modified as well if Bits keeps the name 'bitSize' for its method. In general these kind of breakages has been very painful in the past. Most libraries need to support the last two or three released versions of GHC (and thus base) so breaking changes like this are likely to result in lots of #ifdefs in client code to paper over the differences. Perhaps I'm getting old and cranky but I more in the never-break-anything camp than I used to be. -- Johan

On Mon, 13 Aug 2012, Johan Tibell wrote:
On Mon, Aug 13, 2012 at 3:19 PM, Henning Thielemann
wrote: If the method of 'FixedBitSize' is named 'bitSize' then only the type signature will be affected (FixedBitSize constraint instead of Bits). Although I don't know whether this is a good solution.
Imports will have to be modified as well if Bits keeps the name 'bitSize' for its method.
In general these kind of breakages has been very painful in the past. Most libraries need to support the last two or three released versions of GHC (and thus base) so breaking changes like this are likely to result in lots of #ifdefs in client code to paper over the differences.
That's true. How about keeping 'bitSize' as it is, maybe deprecate it in the future, add maybeBitSize to Bits class and add a new class FixedBitSize with method fixedBitSize?

On Mon, Aug 13, 2012 at 3:26 PM, Henning Thielemann
On Mon, 13 Aug 2012, Johan Tibell wrote:
On Mon, Aug 13, 2012 at 3:19 PM, Henning Thielemann
wrote: If the method of 'FixedBitSize' is named 'bitSize' then only the type signature will be affected (FixedBitSize constraint instead of Bits). Although I don't know whether this is a good solution.
Imports will have to be modified as well if Bits keeps the name 'bitSize' for its method.
In general these kind of breakages has been very painful in the past. Most libraries need to support the last two or three released versions of GHC (and thus base) so breaking changes like this are likely to result in lots of #ifdefs in client code to paper over the differences.
That's true. How about keeping 'bitSize' as it is, maybe deprecate it in the future, add maybeBitSize to Bits class and add a new class FixedBitSize with method fixedBitSize?
This sounds more reasonably to me. I don't particularly need a fixedBitSize method, but if people have uses for it go ahead.

I'd be okay with this version of things as well.
Sent from my iPhone
On Aug 13, 2012, at 6:26 PM, Henning Thielemann
On Mon, 13 Aug 2012, Johan Tibell wrote:
On Mon, Aug 13, 2012 at 3:19 PM, Henning Thielemann
wrote: If the method of 'FixedBitSize' is named 'bitSize' then only the type signature will be affected (FixedBitSize constraint instead of Bits). Although I don't know whether this is a good solution.
Imports will have to be modified as well if Bits keeps the name 'bitSize' for its method.
In general these kind of breakages has been very painful in the past. Most libraries need to support the last two or three released versions of GHC (and thus base) so breaking changes like this are likely to result in lots of #ifdefs in client code to paper over the differences.
That's true. How about keeping 'bitSize' as it is, maybe deprecate it in the future, add maybeBitSize to Bits class and add a new class FixedBitSize with method fixedBitSize?

Throwing Integer out of Bits seems more prone to induce breakage than providing a more accurate type for bitSize -- I know at least one of my modules for working with boolean rings would have be scrapped.
It is also likely to force users who wanted the bit operations they already had on Integer to create wonky local instances to get back behavior the previously had available.
Given my druthers at this point I'd go for:
Making a subclass to move the existing bitSize to, replete with a default definition.
class Bits b => FiniteBits b where
bitSize :: b -> Int
bitSize = fromJust . perhapsBitSize
and adding the perhapsBitSize Lennart suggested to BitSize to replace the moved bitSize:
class Bits b where
perhapsBitSize :: b -> Maybe Int
...
Then code that only works for finite cases can use bitSize, code that already worked with infinite cases that never touched bitSize can continue to work, existing users that called bitSize but could only handle finite cases can change to FiniteBits and doesn't need to take a performance hit or fiddling with the Just constructor, and code that can work for the infinite case if it didn't crap out with bottom can safely upgrade to perhapsBitSize.
I am not wedded to the perhapsBitSize name. I am wedded to not losing existing functionality unnecessarily, however.
Sent from my iPhone
On Aug 13, 2012, at 6:13 PM, Johan Tibell
On Mon, Aug 13, 2012 at 2:48 PM, Henning Thielemann
wrote: How about two versions of 'bitSize' - one with Maybe return type in the Bits class and one without Maybe in a FixedBitSize subclass?
Is this worth breaking existing users of bitSize over? If anything it seems more worthwhile to throw out Integer from the Bits class and declare Bits to be for fixed sized entities.

On Mon, Aug 13, 2012 at 3:42 PM, Edward Kmett
Throwing Integer out of Bits seems more prone to induce breakage than providing a more accurate type for bitSize -- I know at least one of my modules for working with boolean rings would have be scrapped.
It is also likely to force users who wanted the bit operations they already had on Integer to create wonky local instances to get back behavior the previously had available.
Given my druthers at this point I'd go for:
Making a subclass to move the existing bitSize to, replete with a default definition.
class Bits b => FiniteBits b where bitSize :: b -> Int bitSize = fromJust . perhapsBitSize
and adding the perhapsBitSize Lennart suggested to BitSize to replace the moved bitSize:
class Bits b where perhapsBitSize :: b -> Maybe Int ...
I know I've been quite after stirring up some of this discussion. In general I am happy with this suggestion from Edward (+1) and am willing to fix up any breakage in my libraries, though I feel like much of this debate is due to insufficient type class machinery in the language that we should discuss some day. Thomas
Then code that only works for finite cases can use bitSize, code that already worked with infinite cases that never touched bitSize can continue to work, existing users that called bitSize but could only handle finite cases can change to FiniteBits and doesn't need to take a performance hit or fiddling with the Just constructor, and code that can work for the infinite case if it didn't crap out with bottom can safely upgrade to perhapsBitSize.
I am not wedded to the perhapsBitSize name. I am wedded to not losing existing functionality unnecessarily, however.
Sent from my iPhone
On Aug 13, 2012, at 6:13 PM, Johan Tibell
wrote: On Mon, Aug 13, 2012 at 2:48 PM, Henning Thielemann
wrote: How about two versions of 'bitSize' - one with Maybe return type in the Bits class and one without Maybe in a FixedBitSize subclass?
Is this worth breaking existing users of bitSize over? If anything it seems more worthwhile to throw out Integer from the Bits class and declare Bits to be for fixed sized entities.

On Mon, Aug 13, 2012 at 3:42 PM, Edward Kmett
Then code that only works for finite cases can use bitSize, code that already worked with infinite cases that never touched bitSize can continue to work, existing users that called bitSize but could only handle finite cases can change to FiniteBits and doesn't need to take a performance hit or fiddling with the Just constructor, and code that can work for the infinite case if it didn't crap out with bottom can safely upgrade to perhapsBitSize.
This will still break client code though. The #ifdefs would then have to go in the import lists instead. I like Lennart's suggestion to deprecate 'bitSize' but not remove it.

On Mon, Aug 13, 2012 at 06:42:54PM -0400, Edward Kmett wrote:
class Bits b where perhapsBitSize :: b -> Maybe Int ...
I am not wedded to the perhapsBitSize name
I've lost track of where this proposal is, but if we do end up with a Maybe function then I think it should be called maybeBitSize or bitSizeMaybe. The only analogous example in the core libraries that I can think of OTTOMH is Text.Read.readMaybe. Thanks IAn

To summarize the design we've converged upon during the discussion period for Ian: We want to add
class Bits b where bitSizeMaybe :: b -> Maybe Int
and deprecate, but not remove bitSize this iteration, and make a separate class FiniteBits for things with a finite, fixed number of bits:
class Bits b => FiniteBits b where finiteBitSize :: b -> Int finiteBitSize = bitSize
The former permits safer access to bitSize while allowing applications that
can deal with infinite structures to run, the latter permits safer access
to bitSize while allowing applications that cannot deal with infinite
structures to know that they aren't dealing with Integer or somebody's
Natural data type.
-Edward
On Wed, Aug 22, 2012 at 5:19 PM, Ian Lynagh
On Mon, Aug 13, 2012 at 06:42:54PM -0400, Edward Kmett wrote:
class Bits b where perhapsBitSize :: b -> Maybe Int ...
I am not wedded to the perhapsBitSize name
I've lost track of where this proposal is, but if we do end up with a Maybe function then I think it should be called maybeBitSize or bitSizeMaybe. The only analogous example in the core libraries that I can think of OTTOMH is Text.Read.readMaybe.
Thanks IAn
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

On Wed, Aug 22, 2012 at 07:49:49PM -0400, Edward Kmett wrote:
deprecate, but not remove bitSize this iteration, and make a separate class FiniteBits for things with a finite, fixed number of bits:
class Bits b => FiniteBits b where finiteBitSize :: b -> Int finiteBitSize = bitSize
Isn't giving that default implementation a bad idea? Any instance that uses it wiill just break when the deprecated bitSize is removed. Thanks Ian

On Sun, 26 Aug 2012, Ian Lynagh wrote:
On Wed, Aug 22, 2012 at 07:49:49PM -0400, Edward Kmett wrote:
deprecate, but not remove bitSize this iteration, and make a separate class FiniteBits for things with a finite, fixed number of bits:
class Bits b => FiniteBits b where finiteBitSize :: b -> Int finiteBitSize = bitSize
Bit size is always finite in strict data types, isn't it? I suggest a name containing "Fixed".

FixedBits?
Sent from my iPhone
On Aug 26, 2012, at 4:53 PM, Henning Thielemann
On Sun, 26 Aug 2012, Ian Lynagh wrote:
On Wed, Aug 22, 2012 at 07:49:49PM -0400, Edward Kmett wrote:
deprecate, but not remove bitSize this iteration, and make a separate class FiniteBits for things with a finite, fixed number of bits:
class Bits b => FiniteBits b where finiteBitSize :: b -> Int finiteBitSize = bitSize
Bit size is always finite in strict data types, isn't it? I suggest a name containing "Fixed".
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

Wouldn't it be possible to have an instance Bits ByteString, or Vector
Bool or something, where the bitsize would depend on the bytestring
length, and hence wouldn't be fixed?
(although if we're catering for that sort of use, the docs will need
to be changed)
On Sun, Aug 26, 2012 at 9:53 PM, Henning Thielemann
On Sun, 26 Aug 2012, Ian Lynagh wrote:
On Wed, Aug 22, 2012 at 07:49:49PM -0400, Edward Kmett wrote:
deprecate, but not remove bitSize this iteration, and make a separate class FiniteBits for things with a finite, fixed number of bits:
class Bits b => FiniteBits b where finiteBitSize :: b -> Int finiteBitSize = bitSize
Bit size is always finite in strict data types, isn't it? I suggest a name containing "Fixed".
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

On Tue, Aug 28, 2012 at 9:07 AM, Ben Millwood
Wouldn't it be possible to have an instance Bits ByteString, or Vector Bool or something, where the bitsize would depend on the bytestring length, and hence wouldn't be fixed?
You mean like NumLazyByteString [1]? Not only possible but its done at least once (poorly) and deprecated. [1] hackage.haskell.org/packages/archive/NumLazyByteString/0.0.0.1/doc/html/src/Data-ByteString-Lazy-Num.html
(although if we're catering for that sort of use, the docs will need to be changed)
On Sun, Aug 26, 2012 at 9:53 PM, Henning Thielemann
wrote: On Sun, 26 Aug 2012, Ian Lynagh wrote:
On Wed, Aug 22, 2012 at 07:49:49PM -0400, Edward Kmett wrote:
deprecate, but not remove bitSize this iteration, and make a separate class FiniteBits for things with a finite, fixed number of bits:
class Bits b => FiniteBits b where finiteBitSize :: b -> Int finiteBitSize = bitSize
Bit size is always finite in strict data types, isn't it? I suggest a name containing "Fixed".
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

The problem is that right now bitSize is deliberately excluded from looking
at its argument to determine the number of bits in it. You _really_ want a
different combinator. Almost every user of bitSize is passing it undefined,
not a real value.
On Tue, Aug 28, 2012 at 12:07 PM, Ben Millwood
Wouldn't it be possible to have an instance Bits ByteString, or Vector Bool or something, where the bitsize would depend on the bytestring length, and hence wouldn't be fixed?
(although if we're catering for that sort of use, the docs will need to be changed)
On Sun, Aug 26, 2012 at 9:53 PM, Henning Thielemann
wrote: On Sun, 26 Aug 2012, Ian Lynagh wrote:
On Wed, Aug 22, 2012 at 07:49:49PM -0400, Edward Kmett wrote:
deprecate, but not remove bitSize this iteration, and make a separate class FiniteBits for things with a finite, fixed number of bits:
class Bits b => FiniteBits b where finiteBitSize :: b -> Int finiteBitSize = bitSize
Bit size is always finite in strict data types, isn't it? I suggest a
name
containing "Fixed".
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

Hold on, we /do/ get a different combinator, because we're introducing
this new typeclass anyway, and bitSize is being deprecated. So why not
stop excluding it from looking at its argument? Now's a better time
than later to do so :)
(Sorry this is late; I was originally going to comment to Henning that
we hadn't necessarily agreed on Fixed because of my argument, but then
realised someone had objected to my argument, but then realised that
that objection was possibly invalid).
On Tue, Aug 28, 2012 at 6:18 PM, Edward Kmett
The problem is that right now bitSize is deliberately excluded from looking at its argument to determine the number of bits in it. You _really_ want a different combinator. Almost every user of bitSize is passing it undefined, not a real value.
On Tue, Aug 28, 2012 at 12:07 PM, Ben Millwood
wrote: Wouldn't it be possible to have an instance Bits ByteString, or Vector Bool or something, where the bitsize would depend on the bytestring length, and hence wouldn't be fixed?
(although if we're catering for that sort of use, the docs will need to be changed)
On Sun, Aug 26, 2012 at 9:53 PM, Henning Thielemann
wrote: On Sun, 26 Aug 2012, Ian Lynagh wrote:
On Wed, Aug 22, 2012 at 07:49:49PM -0400, Edward Kmett wrote:
deprecate, but not remove bitSize this iteration, and make a separate class FiniteBits for things with a finite, fixed number of bits:
class Bits b => FiniteBits b where finiteBitSize :: b -> Int finiteBitSize = bitSize
Bit size is always finite in strict data types, isn't it? I suggest a name containing "Fixed".
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

On Sun, Sep 23, 2012 at 8:53 PM, Ben Millwood
Hold on, we /do/ get a different combinator, because we're introducing this new typeclass anyway, and bitSize is being deprecated. So why not stop excluding it from looking at its argument? Now's a better time than later to do so :)
I'm rather strongly against this idea. Personally, I think a version of this that counts up "how many bits something actually has given a particular value" is a very different operation. Every application I currently have quite frankly doesn't have a value lying around to pass and it would render the operation useless to many (most?) of its current consumers. A large part of the motivation for the second method was that it didn't have to box and unbox a Maybe, e.g. for HAMTs, that may not know the number of bits they can fit in, say, an Int on a given platform and many of the combinators are constructing an mask out of whole cloth given only the type. It strikes me as a bit of a rule of thumb on what is in base that the classes that are there are the things needed to implement the types that are there. There currently isn't a type in base that needs this extra behavior, so I think it would be reasonable that the method and class live in a module related somehow to the use-case. I don't object to creating yet another class somewhere. I just don't know that it belongs in base or should complicate an already complicated proposal/implementation, and I definitely think it is a different method than the one we've been talking about so far. -Edward
(Sorry this is late; I was originally going to comment to Henning that we hadn't necessarily agreed on Fixed because of my argument, but then realised someone had objected to my argument, but then realised that that objection was possibly invalid).
On Tue, Aug 28, 2012 at 6:18 PM, Edward Kmett
wrote: The problem is that right now bitSize is deliberately excluded from looking at its argument to determine the number of bits in it. You _really_ want a different combinator. Almost every user of bitSize is passing it undefined, not a real value.
On Tue, Aug 28, 2012 at 12:07 PM, Ben Millwood
wrote:
Wouldn't it be possible to have an instance Bits ByteString, or Vector Bool or something, where the bitsize would depend on the bytestring length, and hence wouldn't be fixed?
(although if we're catering for that sort of use, the docs will need to be changed)
On Sun, Aug 26, 2012 at 9:53 PM, Henning Thielemann
wrote: On Sun, 26 Aug 2012, Ian Lynagh wrote:
On Wed, Aug 22, 2012 at 07:49:49PM -0400, Edward Kmett wrote:
deprecate, but not remove bitSize this iteration, and make a
separate
class FiniteBits for things with a finite, fixed number of bits:
> class Bits b => FiniteBits b where > finiteBitSize :: b -> Int > finiteBitSize = bitSize
Bit size is always finite in strict data types, isn't it? I suggest a name containing "Fixed".
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

Well, okay, fair enough. The way you originally phrased it made it
sound like the current design was a problem that we regrettably had to
live with, but if it's actually what you want then I won't argue with
that.
In which case FixedBits sounds like a good idea. I don't think
FiniteBits is sufficiently bad an idea to worry about it, though.
(In any case, I'm not sure Henning's assertion that strict types have
finite bits is correct: after all, bitSize appears to be about the
capacity of the type, rather than how many bits it uses, so in the
case of Integer there is no finite size limit).
On Mon, Sep 24, 2012 at 4:42 AM, Edward Kmett
On Sun, Sep 23, 2012 at 8:53 PM, Ben Millwood
wrote: Hold on, we /do/ get a different combinator, because we're introducing this new typeclass anyway, and bitSize is being deprecated. So why not stop excluding it from looking at its argument? Now's a better time than later to do so :)
I'm rather strongly against this idea. Personally, I think a version of this that counts up "how many bits something actually has given a particular value" is a very different operation. Every application I currently have quite frankly doesn't have a value lying around to pass and it would render the operation useless to many (most?) of its current consumers.
A large part of the motivation for the second method was that it didn't have to box and unbox a Maybe, e.g. for HAMTs, that may not know the number of bits they can fit in, say, an Int on a given platform and many of the combinators are constructing an mask out of whole cloth given only the type.
It strikes me as a bit of a rule of thumb on what is in base that the classes that are there are the things needed to implement the types that are there. There currently isn't a type in base that needs this extra behavior, so I think it would be reasonable that the method and class live in a module related somehow to the use-case. I don't object to creating yet another class somewhere.
I just don't know that it belongs in base or should complicate an already complicated proposal/implementation, and I definitely think it is a different method than the one we've been talking about so far.
-Edward
(Sorry this is late; I was originally going to comment to Henning that we hadn't necessarily agreed on Fixed because of my argument, but then realised someone had objected to my argument, but then realised that that objection was possibly invalid).
On Tue, Aug 28, 2012 at 6:18 PM, Edward Kmett
wrote: The problem is that right now bitSize is deliberately excluded from looking at its argument to determine the number of bits in it. You _really_ want a different combinator. Almost every user of bitSize is passing it undefined, not a real value.
On Tue, Aug 28, 2012 at 12:07 PM, Ben Millwood
wrote: Wouldn't it be possible to have an instance Bits ByteString, or Vector Bool or something, where the bitsize would depend on the bytestring length, and hence wouldn't be fixed?
(although if we're catering for that sort of use, the docs will need to be changed)
On Sun, Aug 26, 2012 at 9:53 PM, Henning Thielemann
wrote: On Sun, 26 Aug 2012, Ian Lynagh wrote:
On Wed, Aug 22, 2012 at 07:49:49PM -0400, Edward Kmett wrote: > > > deprecate, but not remove bitSize this iteration, and make a > separate > class FiniteBits for things with a finite, fixed number of bits: > >> class Bits b => FiniteBits b where >> finiteBitSize :: b -> Int >> finiteBitSize = bitSize
Bit size is always finite in strict data types, isn't it? I suggest a name containing "Fixed".
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

Fair enough.
Sent from my iPhone
On Aug 26, 2012, at 4:38 PM, Ian Lynagh
On Wed, Aug 22, 2012 at 07:49:49PM -0400, Edward Kmett wrote:
deprecate, but not remove bitSize this iteration, and make a separate class FiniteBits for things with a finite, fixed number of bits:
class Bits b => FiniteBits b where finiteBitSize :: b -> Int finiteBitSize = bitSize
Isn't giving that default implementation a bad idea? Any instance that uses it wiill just break when the deprecated bitSize is removed.
Thanks Ian
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

On Wed, Aug 22, 2012 at 07:49:49PM -0400, Edward Kmett wrote:
We want to add
class Bits b where bitSizeMaybe :: b -> Maybe Int
and deprecate, but not remove bitSize this iteration, and make a separate class FiniteBits for things with a finite, fixed number of bits:
class Bits b => FiniteBits b where finiteBitSize :: b -> Int finiteBitSize = bitSize
I've just pushed a patch implementing what I think the conclusion was. Please let me know if you think I got it wrong. Thanks Ian

On Sun, 23 Sep 2012, Ian Lynagh wrote:
On Wed, Aug 22, 2012 at 07:49:49PM -0400, Edward Kmett wrote:
We want to add
class Bits b where bitSizeMaybe :: b -> Maybe Int
and deprecate, but not remove bitSize this iteration, and make a separate class FiniteBits for things with a finite, fixed number of bits:
class Bits b => FiniteBits b where finiteBitSize :: b -> Int finiteBitSize = bitSize
I've just pushed a patch implementing what I think the conclusion was. Please let me know if you think I got it wrong.
My last comment was, that FiniteBits is not an appropriate name, and then we arrived at FixedBits: http://www.haskell.org/pipermail/libraries/2012-August/018349.html

On 2012-09-24 at 01:28:20 +0200, Henning Thielemann wrote:
On Wed, Aug 22, 2012 at 07:49:49PM -0400, Edward Kmett wrote:
We want to add
class Bits b where bitSizeMaybe :: b -> Maybe Int
and deprecate, but not remove bitSize this iteration, and make a separate class FiniteBits for things with a finite, fixed number of bits:
class Bits b => FiniteBits b where finiteBitSize :: b -> Int finiteBitSize = bitSize
I've just pushed a patch implementing what I think the conclusion was. Please let me know if you think I got it wrong.
My last comment was, that FiniteBits is not an appropriate name, and then we arrived at FixedBits: http://www.haskell.org/pipermail/libraries/2012-August/018349.html
As it stands, the current implementation state is at http://git.haskell.org/packages/base.git/commitdiff/cddc9024e67a6d4c01bb1908... Now I have two questions: 1.) Currently, bitSizeMaybe and bitSize have no default implementation defined. Shall we define mutually recursive default implementations for these two functions to help smooth the transition? e.g. in the style (just an example, not an actual proposal) of: bitSize = fromJust . bitSizeMaybe bitSizeMaybe = Just . bitSize 2.) As it's probably not to late to easily fix any bikeshedding/naming issues: Shall the naming remain as implemented? Cheers, hvr

On 2013-09-18 at 13:56:22 +0200, Herbert Valerio Riedel wrote: [...]
As it stands, the current implementation state is at
http://git.haskell.org/packages/base.git/commitdiff/cddc9024e67a6d4c01bb1908...
Now I have two questions:
1.) Currently, bitSizeMaybe and bitSize have no default implementation defined. Shall we define mutually recursive default implementations for these two functions to help smooth the transition?
e.g. in the style (just an example, not an actual proposal) of:
bitSize = fromJust . bitSizeMaybe
bitSizeMaybe = Just . bitSize
2.) As it's probably not to late to easily fix any bikeshedding/naming issues: Shall the naming remain as implemented?
PS: 3.) What's the benefit of having the super-class constraint on class Bits b => FiniteBits b where finiteBitSize :: b -> Int ?

The benefit is that it makes it clear that the notion of Bits and
FiniteBits are related and prevents you from winding up with signatures
that look like (Bits b, FiniteBits b) everywhere.
On Wed, Sep 18, 2013 at 8:07 AM, Herbert Valerio Riedel
On 2013-09-18 at 13:56:22 +0200, Herbert Valerio Riedel wrote:
[...]
As it stands, the current implementation state is at
http://git.haskell.org/packages/base.git/commitdiff/cddc9024e67a6d4c01bb1908...
Now I have two questions:
1.) Currently, bitSizeMaybe and bitSize have no default implementation defined. Shall we define mutually recursive default implementations for these two functions to help smooth the transition?
e.g. in the style (just an example, not an actual proposal) of:
bitSize = fromJust . bitSizeMaybe
bitSizeMaybe = Just . bitSize
2.) As it's probably not to late to easily fix any bikeshedding/naming issues: Shall the naming remain as implemented?
PS:
3.) What's the benefit of having the super-class constraint on
class Bits b => FiniteBits b where finiteBitSize :: b -> Int
? _______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

I believe the resolution was to explicitly leave bitSizeMaybe _not_
implemented in terms of bitSize to help ensure it gets filled in correctly.
Im rather neutral on whether we should supply a definition in the other
direction.
-Edward
On Wed, Sep 18, 2013 at 7:56 AM, Herbert Valerio Riedel
On 2012-09-24 at 01:28:20 +0200, Henning Thielemann wrote:
On Wed, Aug 22, 2012 at 07:49:49PM -0400, Edward Kmett wrote:
We want to add
class Bits b where bitSizeMaybe :: b -> Maybe Int
and deprecate, but not remove bitSize this iteration, and make a separate class FiniteBits for things with a finite, fixed number of bits:
class Bits b => FiniteBits b where finiteBitSize :: b -> Int finiteBitSize = bitSize
I've just pushed a patch implementing what I think the conclusion was. Please let me know if you think I got it wrong.
My last comment was, that FiniteBits is not an appropriate name, and then we arrived at FixedBits: http://www.haskell.org/pipermail/libraries/2012-August/018349.html
As it stands, the current implementation state is at
http://git.haskell.org/packages/base.git/commitdiff/cddc9024e67a6d4c01bb1908...
Now I have two questions:
1.) Currently, bitSizeMaybe and bitSize have no default implementation defined. Shall we define mutually recursive default implementations for these two functions to help smooth the transition?
e.g. in the style (just an example, not an actual proposal) of:
bitSize = fromJust . bitSizeMaybe
bitSizeMaybe = Just . bitSize
2.) As it's probably not to late to easily fix any bikeshedding/naming issues: Shall the naming remain as implemented?
Cheers, hvr _______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

On 2013-09-18 at 17:22:06 +0200, Edward Kmett wrote:
I believe the resolution was to explicitly leave bitSizeMaybe _not_ implemented in terms of bitSize to help ensure it gets filled in correctly.
Im rather neutral on whether we should supply a definition in the other direction.
Me too... so we'd have something like bitSize :: a -> Int bitSize = fromJust . bitSizeMaybe Then one benefit might be, that when you build-dep on the new base>=4.7, you can start writing instances ignoring the deprecated `bitSize` method, and just define `bitSizeMaybe`, and then the legacy `bitSize` will be implicitly defined as well. When `bitSize` is finally removed, your instance definition won't have to be adapted. But I'm not sure if this convenience is enough to justify such a default implementation. Cheers, hvr

On Sun, 29 Jul 2012, Thomas Schilling wrote:
On 29 July 2012 15:37, Thomas DuBuisson
wrote: That is a great point. Most my uses of 'bitSize' are monomorphic and Maybe would just be silly. OTOH, I'd be more than happy to fix up any polymorphic code to include a new BitSize constraint.
To make sure I understand this correctly:
The current problem is that bitSize is a partial function *depending on the type* of its argument (currently it always returns _|_ for Integer, and is total for any other type). That does indeed seem like a Bad Idea.
You propose to:
1. Remove "bitSize" from the Bits class. 2. Add a new class BitSize which only contains the "bitSize" method. Integer would not be an instance of this class.
+1
participants (13)
-
Andreas Abel
-
Antoine Latter
-
Ben Millwood
-
Edward Kmett
-
Henning Thielemann
-
Herbert Valerio Riedel
-
Ian Lynagh
-
Ian Lynagh
-
Johan Tibell
-
John Lato
-
Lennart Augustsson
-
Thomas DuBuisson
-
Thomas Schilling