我正在定义Octave类型:
data Octave = 1 | 2 | 3
deriving (Show, Read, Ord, Enum)
Run Code Online (Sandbox Code Playgroud)
由于'1'对数据构造函数标识符无效,我必须这样做:
data Octave = O1 | O2 | O3
deriving (Show, Eq, Read, Ord, Enum)
Run Code Online (Sandbox Code Playgroud)
现在,如果我show Octave O1
显示"O1",这不是我想要的.我希望结果为"1".我知道我们可以像这样定制我们的Show行为:
instance Show Blabla where
show (Blabla ints chars list num) =
"integers = " ++ show ints ++ "\n"
Run Code Online (Sandbox Code Playgroud)
但问题是我使用的是枚举类型,这意味着除了标识符名称'O1'之外它没有值.我怎样才能在Haskell中访问它?
另一个问题:我怎么读回来?
read "O1" :: Octave
工作,但我想 read "1" :: Octave
instance Read Octave where
read "1" = O1
read "2" = O2
read "3" = O3
Run Code Online (Sandbox Code Playgroud)
这不起作用:" read
不是(可见的)类方法Read
".
利用Octave的Enum
实例并使用Show
和Read
实例,Int
我们可以实现这样的显示和读取:
data Octave = O1 | O2 | O3 deriving (Eq, Ord, Enum)
instance Show Octave where
show o = show (fromEnum o + 1)
instance Read Octave where
readsPrec prec = map (\(n,s) -> (toEnum (n - 1), s)) . readsPrec prec
Run Code Online (Sandbox Code Playgroud)
即fromEnum
,toEnum
在八度和整数之间进行转换,以便O1
< - > 0
和O2
< - > 1
,因此我们必须在读取和写入时调整一个.
这是一种不同的方法:
data Octave_ = O1 | O2 | O3 deriving (Show, Eq, Read, Ord, Enum)
newtype Octave = O { unO :: Octave_ } deriving (Eq, Ord, Enum)
instance Show Octave where
show = tail . show . unO
Run Code Online (Sandbox Code Playgroud)
根据你正在做的事情,这可能是好事还是坏事.