我正在尝试定义一种数据类型来表示二进制,八进制和十六进制的数字。我的想法是使用这种数据类型定义一些函数,以便从八进制转换为二进制,从二进制转换为十六进制,从八进制转换为十六进制
这就是我现在所拥有的......
data Number = Bin[Char] | Hex[Char]| Oct[Char]
deriving Show
oct2Bin :: Number -> Number
bin2Hex :: Number -> Number
oct2Hex :: Number -> Number
但我被困在这里,我不知道我是否走在正确的轨道上。我很感激能帮到这个问题。
答案 0 :(得分:4)
您应该简单地将数字保存为数字类型之一,最好是整数。这样,您就可以轻松使用
这样的功能type Base = Int
type Number = Integral
repr :: Integral a => Base -> a -> String
但也许已经有这样的功能?事实上,有(Numeric
):
showIntAtBase :: (Integral a, Show a) =>
a -- the base
-> (Int -> Char) -- a function to transform single digits
-- (in that base)
-> a -- the number
-> ShowS -- ShowS = String -> String
因此,repr base number
只是showIntAtBase base conv number ""
:
repr base number = showIntAtBase base conv number ""
where conv n = (['0'..'9'] ++ ['a'..'z']) !! n
虽然您可能希望将conv
更改为其他内容。
此外,Numeric
已包含showHex
和showOct
。 showBinary
不在那里,但与上面的repr一起就像showBin = repr 2
一样简单。
答案 1 :(得分:1)
为什么不使用Int
来表示您的号码,当您出于某种原因需要字符串表示时,请使用Number -> String
函数?例如:
type Number = Int
toBin :: Number -> String
toOct :: Number -> String
toHex :: Number -> String
toOct = show
... implement others as usual ...
使用像这样的规范表示(在这种情况下,我们的表示形式为Int),您可以最小化类型之间所需的转换。此类型的所有操作都可以无需转换即可运行。只有在需要字符串表示时才会进行转换。
(@Karoly在评论中也提到了组合爆炸的问题,但是只要你保证所有格式都可以传递,我认为你可以避免它 - 即使你的实现效率可能非常低效)