haskell / haskell/core-libraries-committee
Remove `sizeOf (undefined :: a)` pattern from classes in base
- Dominant language
- Haskell
- Stars
- 109
- Forks
- 20
- PR merge metrics
- No merged PRs in 30d
Description
# Motivation
The current pattern for figuring out a class-wide value is having a function in that class which takes an argument and ignores it, and passing it `undefined` set to that type. However, this is bad because it allows users to write instances which inspect their arguments and return different values for different inputs, and error on being passed `undefined`. We should make illegal states unrepresentable whenever possible.
# Proposal
Classes with these properties should have methods which visibly do not refer to their argument. This can be accomplished in several ways:
```haskell
-- proxy method
sizeOfP :: p a -> Int
-- Tagged value (requires bringing in the tagged package)
sizeOfT :: Tagged a Int
-- Const value
sizeOfC :: Const Int a
```
These have different benefits and drawbacks, and the choice should be decided on democratically. I prefer the `Const` method, because once the value in the dictionary is evaluated, it's evaluated forever.
# Process
Suppose we go with the `Const` method. This will cause these methods to be added to the class, the `MINIMAL` pragma updated, and they'll be given defaults like so:
```haskell
sizeOfC :: Const Int a
sizeOfC = Const (sizeOf (undefined :: a))
sizeOf :: a -> Int
sizeOf _ = getConst (sizeOfC :: Const Int a)
```
After a while (at least a major version number change), the versions which take `undefined` will be deprecated. After another while, they'll be moved out of the class and become normal methods:
```haskell
sizeOf :: forall a. Storable a => a -> Int
sizeOf _ = getConst (sizeOfC :: Const Int a)
```
I feel like eventually they should be eliminated.
# Impact
The following classes and methods that I've found are impacted:
* `Data.Bits.Bits`: `bitSizeMaybe`, `bitSize`, `isSigned`
* `Data.Bits.FiniteBits`: `finiteBitSize`
* `Foreign.Storable`: `sizeOf`, `alignment`
* `Prelude.RealFloat`: `floatRadix`, `floatDigits`, `floatRange`
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by reading the class and method definitions in Data.Bits.Bits, Data.Bits.FiniteBits, Foreign.Storable, and Prelude.RealFloat. Compare the proxy, Tagged, and Const approaches against their defaults, MINIMAL pragmas, and compatibility implications. Done means the project has a decided approach and an agreed migration and deprecation plan for all listed methods.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- haskell
- Domain
- backend-api-design
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100