Discussion:
Proposal: add `Proxy`fied versions of `bitSizeMaybe` and `finiteBitSize`
M Farkas-Dyck
2017-12-14 03:48:10 UTC
Permalink
I propose to add the following methods to `Bits` and `FiniteBits` classes:

class Bits a where
...

bitSizeMaybe' :: Proxy a -> Maybe Int

class FiniteBits b where
...

finiteBitSize' :: Proxy b -> Int

Rationale: working with an arbitrary `Bits a => a`, one may not have a value of type `a` as argument to `bitSizeMaybe` or `finiteBitSize`, and writing `undefined` makes me feel dirty.
David Feuer
2017-12-14 04:19:47 UTC
Permalink
+1, but we should also do this for sizeOf and alignment in Foreign.Storable.
Post by M Farkas-Dyck
class Bits a where
...
bitSizeMaybe' :: Proxy a -> Maybe Int
class FiniteBits b where
...
finiteBitSize' :: Proxy b -> Int
Rationale: working with an arbitrary `Bits a => a`, one may not have a
value of type `a` as argument to `bitSizeMaybe` or `finiteBitSize`, and
writing `undefined` makes me feel dirty.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
M Farkas-Dyck
2017-12-14 04:41:47 UTC
Permalink
Post by David Feuer
+1, but we should also do this for sizeOf and alignment in Foreign.Storable.
Yes, good idea
Zemyla
2017-12-14 05:37:47 UTC
Permalink
I honestly think we should make it a Const Int a, instead of a
function, so that it's a number in the typeclass dictionary and not a
function.
Post by M Farkas-Dyck
Post by David Feuer
+1, but we should also do this for sizeOf and alignment in
Foreign.Storable.
Yes, good idea
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Tikhon Jelvis
2017-12-14 05:41:22 UTC
Permalink
The Const type does not see much direct use in other common Haskell
packages. (I only ever encounter it through lens.) So while that might be
an elegant design, I think it will make the API more confusing for
newcomers.
Post by Zemyla
I honestly think we should make it a Const Int a, instead of a
function, so that it's a number in the typeclass dictionary and not a
function.
Post by M Farkas-Dyck
Post by David Feuer
+1, but we should also do this for sizeOf and alignment in
Foreign.Storable.
Yes, good idea
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
M Farkas-Dyck
2017-12-14 07:09:00 UTC
Permalink
Post by Zemyla
I honestly think we should make it a Const Int a, instead of a
function, so that it's a number in the typeclass dictionary and not a
function.
I like that idea!
Post by Zemyla
The Const type does not see much direct use in other common Haskell packages. (I only ever encounter it through lens.) So while that might be an elegant design, I think it will make the API more confusing for newcomers.
I doubt whether it's much more confusing than `Proxy`, and would be more efficient in cases where the typeclass dictionary can't be inline. Anyhow, if we began using it in base it would thus gain exposure; it's self-fulfilling either way.
Henning Thielemann
2017-12-14 08:38:46 UTC
Permalink
I honestly think we should make it a Const Int a, instead of a function,
so that it's a number in the typeclass dictionary and not a function.
Even better.
Andrew Martin
2017-12-14 12:16:08 UTC
Permalink
Alternatively, we could have it be `Proxy# a -> Int`, which should have
identical performance characteristics to `Const Int a` but with the added
benefit that it's a little easier to understand how it's supposed to be
used.
Post by Zemyla
I honestly think we should make it a Const Int a, instead of a
function, so that it's a number in the typeclass dictionary and not a
function.
Post by M Farkas-Dyck
Post by David Feuer
+1, but we should also do this for sizeOf and alignment in
Foreign.Storable.
Yes, good idea
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
-Andrew Thaddeus Martin
Henning Thielemann
2017-12-14 08:36:57 UTC
Permalink
Post by David Feuer
+1, but we should also do this for sizeOf and alignment in Foreign.Storable.
That was my intended reply ...
Henning Thielemann
2017-12-19 09:17:30 UTC
Permalink
Post by David Feuer
+1, but we should also do this for sizeOf and alignment in Foreign.Storable.
If Storable would be intended for tuples, too, and there would be no
padding, we could use special Monoids in Const, like so:

class Storable a where
sizeOf :: Const (Sum Int) a
alignment :: Const (LCM Int) a

instance (Storable a, Storable b) => Storable (a,b) where
sizeOf = liftA2 (,) sizeOf sizeOf
alignment = liftA2 (,) alignment alignment


Taking alignment into account we could define

data SizeAlign = SignAlign {sizeOf_, alignment_ :: Int}

instance Monoid SizeAlign where
mempty = SizeAlign 0 1
mappend x y =
SizeAlign
(sizeOf_ x + mod (- sizeOf_ x) (alignment_ y) + sizeOf_ y)
(lcm (alignment_ x) (alignment_ y))

class Storable a where
sizeAlign :: Const SizeAlign a

instance (Storable a, Storable b) => Storable (a,b) where
sizealign = liftA2 (,) sizeOf sizeOf

However, SizeAlign.mappend this way is not valid because it violates
associativity (e.g. sizes 1, 1, 2 with corresponding alignments). Even if
it would be valid, it would still differ e.g. from Linux-x86 ABI, since
structs are already padded to the next aligned size.

At least for the alignments an LCM monoid would work.

Henning Thielemann
2017-12-14 08:43:57 UTC
Permalink
Post by M Farkas-Dyck
class Bits a where
...
bitSizeMaybe' :: Proxy a -> Maybe Int
class FiniteBits b where
...
finiteBitSize' :: Proxy b -> Int
Alternative suggestion for names (I frequently overlook the primes):
bitSizeMaybeConst :: Const (Maybe Int) a
finiteBitSizeConst :: Const Int a
sizeOfConst :: Const Int a
alignmentConst :: Const Int a

Then we must add mutual default implementations in order to preserve
existing instances.
Ryan Scott
2017-12-14 13:15:02 UTC
Permalink
I don't have a particular opinion on this proposal, but I did want to
chime in to note that there are several other functions in base
besides biteSizeMaybe, finiteBitSize, sizeOf, and alignment that take
a dummy argument. The last time I checked, all of these functions also
fit the bill [1]:

* Data.Bits.isSigned :: Bits a => a -> Bool
* Data.Data.dataTypeOf :: Data a => a -> DataType
* GHC.Generics.datatypeName :: Datatype d => t d f a -> String
* GHC.Generics.moduleName :: Datatype d => t d f a -> String
* GHC.Generics.isNewtype :: Datatype d => t d f a -> Bool
* GHC.Generics.packageName :: Datatype d => t d f a -> String
* GHC.Generics.conName :: Constructor c => t c f a -> String
* GHC.Generics.conFixity :: Constructor c => t c f a -> Fixity
* GHC.Generics.conIsRecord :: Constructor c => t c f a -> Bool
* GHC.Generics.selName :: Selector s => t s f a -> String
* GHC.Generics.selSourceUnpackedness :: Selector s => t s f a ->
SourceUnpackedness
* GHC.Generics.selSourceStrictness :: Selector s => t s f a -> SourceStrictness
* GHC.Generics.selDecidedStrictness :: Selector s => t s f a ->
DecidedStrictness
* Prelude.floatRadix :: RealFloat => a -> Integer
* Prelude.floatDigits :: RealFloat => a -> (Int, Int)
* Text.Printf :: PrintfArg a => a -> ModifierParser

Ryan S.
-----
[1] This list was taken from
http://hackage.haskell.org/package/proxied-0.3/docs/Data-Proxied.html
Henning Thielemann
2017-12-14 13:46:52 UTC
Permalink
Now that we have visible type application, we could stop using these Proxy arguments, thus
class Bits a where
...
bitSizeMaybe' :: Maybe Int
And you invoke it by saying
rather than
bitSizeMaybe (Proxy :: Proxy T)
Looks like a straight win to me.
I was not aware of this type extension, but I still prefer Haskell 98 /
2010.
M Farkas-Dyck
2017-12-14 20:11:19 UTC
Permalink
I still prefer Haskell 98 / 2010.
I agree. I would hesitate to introduce ambiguous types here.
Edward Kmett
2017-12-15 14:08:22 UTC
Permalink
This was my knee-jerk reaction as well, but interestingly, you only
actually need to turn on AllowAmbiguousTypes to compile the class. You can
actually _use_ the methods without the extension. This matters to me
because AllowAmbiguousTypes allows far too many errors through in user code.

This renders it a somewhat less bad option than I previously assumed and
leaves me somewhat ambivalent about whether we use the extension or not.
Post by M Farkas-Dyck
I still prefer Haskell 98 / 2010.
I agree. I would hesitate to introduce ambiguous types here.
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Loading...