#4443: Don't require users to use undefined
---------------------------------+------------------------------------------
Reporter: basvandijk | Owner:
Type: proposal | Status: new
Priority: normal | Component: libraries/base
Version: 6.12.3 | Keywords:
Testcase: | Blockedby:
Os: Unknown/Multiple | Blocking:
Architecture: Unknown/Multiple | Failure: None/Unknown
---------------------------------+------------------------------------------
Users of the `sizeOf` or `alignment` methods (`:: a -> Int`) of the
`Storable` class are pushed to use `undefined` in their programs. Take the
following function from `Foreign.Marshal.Alloc` as an example:
{{{
malloc :: Storable a => IO (Ptr a)
malloc = doMalloc undefined
where
doMalloc :: Storable b => b -> IO (Ptr b)
doMalloc dummy = mallocBytes (sizeOf dummy)
}}}
I find the use of `undefined` ugly; its only purpose is to help the type-
checker by carrying around a type variable. It also makes the job of an
optimizing compiler harder because, in order to avoid generating
unnecessary code, the compiler needs to find out if `undefined` isn't
used. More importantly however, `undefined` is dangerous; The type-checker
will never complain when you accidentally use `undefined` in the wrong
place increasing the change that your program will crash. Also, instance
writers for the `Storable` class need to be careful not to evaluate the
argument of `sizeOf` because it may be `undefined`.
The use of `undefined` is not only required by the `Storable` class. Users
of the `HasResolution` class from `Data.Fixed` also need to use
`undefined` in order to get the resolution of a fixed value:
{{{
class HasResolution a where
resolution :: p a -> Integer
}}}
I would like to propose solving this. My proposal consists of 3 sub-
proposals:
1. Add module `Data.Tagged`.
2. Modify the `sizeOf` and `alignment` methods of the `Storable` class.
3. Modify the `HasResolution` class.
What follows are more detailed explanations of the proposals:
== Add module `Data.Tagged` ==
My proposal is to move the `Data.Tagged` module from Edward A. Kmett's
[http://hackage.haskell.org/package/tagged tagged] package to `base`.
The only modification that needs to be done is to drop the `Default`
instance for `Proxy` because this will otherwise require that
`Data.Default` be moved to base as well which isn't my intention. When
this proposal is accepted `Data.Default` can provide the instance instead.
== Modify the `sizeOf` and `alignment` methods of the `Storable` class ==
I would like to replace the following:
{{{
class Storable a where
sizeOf :: a -> Int
alignment :: a -> Int
}}}
with:
{{{
class Storable a where
sizeOf :: SizeOf a
alignment :: Alignment a
type SizeOf a = Tagged a Int
type Alignment a = Tagged a Int
}}}
To retrieve the actual size of type `a` use:
`untag (sizeOf :: SizeOf a)`
where: `untag :: Tagged s b -> b` from `Data.Tagged`.
See the following for the
[http://code.haskell.org/~basvandijk/doc/ghc/html/libraries/base-4.3.0.0
/Foreign-Storable.html haddock documentation].
Here's the definition of the previous `malloc` function to give you an
impression how code looks when my proposals are accepted:
{{{
malloc :: forall a. Storable a => IO (Ptr a)
malloc = mallocBytes (untag (sizeOf :: SizeOf a))
}}}
(Note that this does require the `ScopedTypeVariables` language
extension.)
== Modify the `HasResolution` class ==
I would like to modify the `HasResolution` class in the same way. So
replacing:
{{{
class HasResolution a where
resolution :: p a -> Integer
}}}
with:
{{{
class HasResolution a where
resolution :: Resolution a
type Resolution a = Tagged a Integer
}}}
See the following for the
[http://code.haskell.org/~basvandijk/doc/ghc/html/libraries/base-4.3.0.0
/Data-Fixed.html haddock documentation].
Note that `Fixed` also gets a `HasResolution` instance:
{{{
instance HasResolution a => HasResolution (Fixed a) where
resolution = retag (resolution :: Resolution a)
}}}
where: `retag :: Tagged s b -> Tagged t b` from `Data.Tagged`.
== `bitSize`? ==
There's a possible 4th proposal that I'm thinking about: The `Bits` class
from `Data.Bits` has the `bitSize :: a -> Int` method. Maybe it would be a
good idea to replace that as well with:
`bitSize :: BitSize a; type BitSize a = Tagged a Int`
However I think `bitSize` is more often applied to an actual value than to
`undefined` so I need to investigate that a little further.
== Patches ==
A patch for the `base` package is attached to the ticket. I also attached
patches for the `ghc` compiler, `bytestring`, `binary`, `vector` and
`dph`. The latter are just some packages that were inside my ghc
repository.
== Deadline ==
3 weeks from now (Tuesday 16 November 2010) but I will shift it when the
discussion demands it.
--
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/4443>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
_______________________________________________
Glasgow-haskell-bugs mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs