我正在Haskell中编写一些程序,处理很多基本类型,如Word32 / Word64等。 我使用ghci经常测试函数,在终端中查看结果。
为方便快捷,我总是以十六进制显示数据,例如
data Human = M Int | F Int
instance Show Human where
show M x = printf "man, age %d" x
show F x = printf "woman, age %d" x
但我希望基本类型以十六进制显示(特别是在ghci中)。 我发现实例声明无法覆盖。 并且不想要将它们全部扭曲为:
newtype MyInt = MyInt Int
instance Show MyInt where
...
看起来有点愚蠢。
我可以修改ghc包base
中的一些代码吗?
我只想让一切都变成“十六进制”。我只想要ghci显示“hex”。我怎么能实现它?
由于我们所有人都同意覆盖Show不合适且不切实际, 欢迎使用“更好的方法在ghci中以十六进制显示数字”的任何答案。
答案 0 :(得分:6)
不,没有newtype
s就无法实现这一目标;实例无法覆盖。
如果您真的想要这个,我建议您定义自己的类型类ShowHex
,如Show
,但所有实例都以十六进制打印。但是,我会认为您的Show
实例不正确; Show
个实例是为调试和序列化而设计的,应该输出语法上有效的代码。 1 你的实例没有,所以我建议你定义自己的类型类来显示这些值,或者只是使用一个功能。
为此修改代码是不切实际的;这种实例的语义变化不仅会破坏很多软件包,而且让GHC真正使用你的修改版本也是一件非常痛苦的事。
1 理想情况下,它们生成的代码应该是语义有效的Haskell,它产生一个比较等于show
输入的值,但这不是严格的必要的。
答案 1 :(得分:5)
这会滥用Show
实例。它不是真正意义上的格式。如果要以十六进制显示某些内容,只需使用函数进行转换即可。例如,您可以使用showHex
中的Numeric
来制作这样的小帮手:
> import Numeric
Numeric> let hex x = showHex x ""
Numeric> hex 123456
"1e240"
答案 2 :(得分:2)
一个极端的解决方案是使用{-# LANGUAGE NoImplicitPrelude #-}
,然后导入您自己的“Prelude”。不过,这可能会比你的案子更有价值。
答案 3 :(得分:1)
同意@ehird和@hammar这可能会被滥用。如果想要一些数字总是显示为十六进制,我认为它是合理的,因为" 0xff"是一个数字的合法表示。所以这个:
{-# 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
现在我可以:
> 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
这对我使用低级别的东西非常有用。也许我会把它放在Hackage上。