TL;DR: Should I add support for unlifted types to Witch?
I maintain Witch, a library for converting values between types. At its core, Witch provides this type class:
class From source target where
from :: source -> target
This lets you handle conversions that cannot fail, like going from a Word8
to a Word
:
instance From Word8 Word where
from = fromIntegral
>>> from (15 :: Word8) :: Word
15
I don’t normally work with unlifted types. As a result, Witch doesn’t support them. If you try to define a From
instance between, say, Word8#
and Word#
, you’ll get an error:
instance From Word8# Word# where
from = word8ToWord#
Example.hs:1:15: error:
• Expecting a lifted type, but ‘Word8#’ is unlifted
• In the first argument of ‘From’, namely ‘Word8#’
In the instance declaration for ‘From Word8# Word#’
|
1 | instance From Word8# Word# where
| ^^^^^^
This isn’t a fundamental limitation though. Haskell supports levity polymorphism, so it should be possible to define a type class that would support these conversions. For example:
class FromP (source :: TYPE rep1) (target :: TYPE rep2) where
from :: s -> t
All the old instances would be supported, since rep1
and rep2
would both be 'LiftedRep
.
instance FromP Word8 Word where
from = fromIntegral
This would also support converting between Word8#
and Word#
, since the two runtime representations don’t need to be the same.
instance FromP Word8# Word# where
from = word8ToWord#
And this new type class could even support converting between runtime representations, like from an unlifted Word#
to a lifted Word
.
instance FromP Word8# Word where
from = W#
This seems like a good change to make to the Witch library. It allows more instances to be provided at the cost of a slightly more complicated implementation. But since I only ever use lifted types, I haven’t actually run into this limitation. So I’m wondering: Would this be useful?