Skip to content

GitLab

  • Projects
  • Groups
  • Snippets
  • Help
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in / Register
GHC
GHC
  • Project overview
    • Project overview
    • Details
    • Activity
    • Releases
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 4,322
    • Issues 4,322
    • List
    • Boards
    • Labels
    • Service Desk
    • Milestones
    • Iterations
  • Merge Requests 362
    • Merge Requests 362
  • Requirements
    • Requirements
    • List
  • CI / CD
    • CI / CD
    • Pipelines
    • Jobs
    • Schedules
  • Security & Compliance
    • Security & Compliance
    • Dependency List
    • License Compliance
  • Operations
    • Operations
    • Incidents
    • Environments
  • Analytics
    • Analytics
    • CI / CD
    • Code Review
    • Insights
    • Issue
    • Repository
    • Value Stream
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Members
    • Members
  • Collapse sidebar
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
  • Glasgow Haskell Compiler
  • GHCGHC
  • Issues
  • #14562

Closed
Open
Opened Dec 07, 2017 by Andrew Martin@andrewthadDeveloper

IntRep vs WordRep

Why do Int# and Word# have different runtime representations? By this I mean that:

Int# :: TYPE 'IntRep
Word# :: TYPE 'WordRep

To my understanding, they are always the same size and always live in the same set of registers. The docs for unsafeCoerce# state that it can be used for:

Casting an unboxed type to another unboxed type of the same size (but not coercions between floating-point and integral types)

The implies that a cast between Int# and Word# is acceptable. But if you're able to unsafeCoerce# between two types, shouldn't they be defined as having the same representation?

What I'm suggesting is that it may be better to collapse IntRep and WordRep into a single representation (probably named WordRep). We would then get slightly more reusable code in some cases:

data WordList (x :: TYPE 'WordRep)
  = WordListCons x (WordList x)
  | WordListNil

ints :: WordList Int#
ints = WordListCons 5# (WordListCons 8# WordListNil)


words :: WordList Word#
words = WordListCons 4## (WordListCons 12## WordListNil)

mapWordList :: forall (x :: TYPE 'WordRep). (x -> x) -> WordList x -> WordList x
mapWordList _ WordListNil = WordListNil
mapWordList f (WordListCons x xs) = WordListCons (f x) xs

biggerInts :: WordList Int#
biggerInts = mapWordList (\x -> x +# 3) ints

biggerWords :: WordList Int#
biggerWords = mapWordList (\x -> plusWord# x 3) ints

For additional context, I'd add that, excluding SumRep and TupleRep (because you can produce different nestings with equivalent representations), coercions between types of different representations are always unsound.

Edited Mar 10, 2019 by Andrew Martin
Assignee
Assign to
None
Milestone
None
Assign milestone
Time tracking
None
Due date
None
Reference: ghc/ghc#14562