I\'m writting some programs in Haskell, dealing with a lot of basic types like Word32/Word64 etc.. I use ghci to test the functions frequently, see the results in terminal.<
Agreeing with @ehird and @hammar that this could be abused. In the case of wanting some numbers to always show as hex, I think it's reasonable because "0xff" is a legitimate representation of a number. So this:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module HexNumber where
import Numeric
import Text.Read
import qualified Text.Read.Lex as L
newtype HexInt a = HexInt { int :: a }
deriving (Eq, Ord, Num, Enum)
instance (Show a, Integral a) => Show (HexInt a) where
show hi = "0x" ++ showHex (int hi) ""
instance (Num a) => Read (HexInt a) where
-- Couldn't figure out how to write this instance so just copy/paste from Text.Read
readPrec = readNumber convertInt
readListPrec = readListPrecDefault
readList = readListDefault
readNumber :: Num a => (L.Lexeme -> ReadPrec a) -> ReadPrec a
readNumber convert =
parens
( do x <- lexP
case x of
L.Symbol "-" -> do y <- lexP
n <- convert y
return (negate n)
_ -> convert x
)
convertInt :: Num a => L.Lexeme -> ReadPrec a
convertInt (L.Number n)
| Just i <- L.numberToInteger n = return (fromInteger i)
convertInt _ = pfail
Now I can:
> let x = 10 :: HexInt Int
> x
0xa
> x * 2
0x14
> let x = 10 :: HexInt Integer
> x
0xa
> x * 2
0x14
> read "0xa" :: HexInt Int
0xa
> read "10" :: HexInt Int
0xa
This seems very useful to me working with low-level stuff a lot. Maybe I'll put it on Hackage.
One extreme solution would be to use {-# LANGUAGE NoImplicitPrelude #-}
, and import your own "Prelude" instead. That would probably be a lot more work than it's worth for your case, though.
No, there is no way to achieve this without newtype
s; instances cannot be overriden.
If you really want this, I would suggest defining your own typeclass, ShowHex
, like Show
but with all the instances printing in hex. However, I would consider your Show
instance incorrect; Show
instances are designed for debugging and serialisation, and should output syntactically valid code.1 Yours doesn't, so I would suggest either defining your own typeclass for displaying these values, or simply using a function.
Modifying the code to base for this is impractical; not only would this change in semantics for the instances break a lot of packages, but it'd be a huge pain to get GHC to actually use your modified version.
1 Ideally, the code they produce should be semantically valid Haskell that produces a value comparing equal to show
's input, but this is not strictly necessary.
That would be abusing the Show
instance. It's not really meant for formatting. If you want to show something in hexadecimal, just use a function to do the conversion. For example, you can use showHex
from Numeric
to make a small helper like this:
> import Numeric
Numeric> let hex x = showHex x ""
Numeric> hex 123456
"1e240"