#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

Reply via email to