Opened 3 years ago

Closed 3 years ago

#4443 closed proposal (wontfix)

Don't require users to use undefined

Reported by: basvandijk Owned by:
Priority: normal Milestone: Not GHC
Component: libraries/base Version: 6.12.3
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Difficulty:
Test Case: Blocked By:
Blocking: Related Tickets:

Description

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.
  1. Modify the sizeOf and alignment methods of the Storable class.
  1. 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 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 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 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.

Attachments (6)

base_ticket_4443.dpatch (104.4 KB) - added by basvandijk 3 years ago.
ghc_ticket_4443.dpatch (181.4 KB) - added by basvandijk 3 years ago.
bytestring_ticket_4443.dpatch (5.8 KB) - added by basvandijk 3 years ago.
binary_ticket_4443.dpatch (10.2 KB) - added by basvandijk 3 years ago.
dph_ticket_4443.dpatch (52.1 KB) - added by basvandijk 3 years ago.
vector_ticket_4443.dpatch (1.8 KB) - added by basvandijk 3 years ago.

Download all attachments as: .zip

Change History (9)

Changed 3 years ago by basvandijk

Changed 3 years ago by basvandijk

Changed 3 years ago by basvandijk

Changed 3 years ago by basvandijk

Changed 3 years ago by basvandijk

comment:1 Changed 3 years ago by basvandijk

Thread on the libraries list.

Changed 3 years ago by basvandijk

comment:2 Changed 3 years ago by igloo

  • Milestone set to Not GHC

comment:3 Changed 3 years ago by basvandijk

  • Resolution set to wontfix
  • Status changed from new to closed

I'm closing this ticket as 'wontfix' because most people objected to this proposal. The main reason was: lots of code will break while there's little benefit.

Henning Thielemann proposed an interesting compromise:

Since all of the affected modules are quite basic, this would break a lot
of code. Thus I would propose a less invasive path:

  1. Add functions that provide the Tagged interface and implement them

using 'sizeOf' and 'alignment'.

  1. Add functions that convert a sizeOfTagged and alignmentTagged function

to 'sizeOf' and 'alignment' in order to allow Storable instance
declaration, that not need to cope with undefined.

  1. Document how to use the Tagged types with Haskell 98.
  1. In the future you may deprecate the immediate use of 'sizeOf' and

'alignment'.

Note: See TracTickets for help on using tickets.