我试图使用简短易读的格式来显示和读取我的数据,我希望它可以从Haskell解释器中使用,以便在写入时手写或复制粘贴输入我尝试新功能。
我的数据是一个Int数字列表,每个都有一个布尔属性,我与+
和-
关联,是第一个默认值,所以它不需要显式表示(与通常的符号一样)。我想在数字后面代表-
,就像在这个例子中一样:
[2, 5-, 4, 0-, 1, 6-, 2-]
请注意,我无法使用常规符号,因为我需要能够将-
分配给0
,以便0-
与0
不同(同样,可能在将来我需要使用负数,例如[-4-, -2]
)。
我做了简单的部分,即定义列表术语的数据类型并实现show
函数。
data Term = T Int Bool deriving (Eq)
instance Show Term where
show (T v True) = show v
show (T v False) = show v ++ "-"
我不知道如何执行相应的read
功能,或者我是否不能使用-
符号,因为它是Haskell语言的标志。欢迎提出建议。
答案 0 :(得分:2)
尝试这样的事情:
instance Read Term where
readsPrec n s = do
(i,rest) <- readsPrec (n+1) s -- read `i :: Int`
return $ case rest of -- look at the rest of the string
('-':rest') -> (T i False, rest') -- if it starts with '-'...
rest' -> (T i True, rest') -- if it doesn't...
Haskell中的 Read
密切关注解析器可以由类型String -> [(a, String)]
表示的类型(此类型被赋予类型同义词ReadS
。要熟悉解析的这种想法,我建议阅读以下functional pearl on monadic parsing。
然后,来自GHCi:
ghci> read "[2, 5-, 4, 0-, 1, 6-, 2-]" :: [Term]
[2,5-,4,0-,1,6-,2-]
答案 1 :(得分:1)
我非常喜欢Alec的答案,我接受了。但经过阅读,思考和尝试,我达成了另一个非常简单的解决方案,我想在此分享。
它使用reads
代替readsPrec
,因为Term
构造函数不是中缀,因此我们不需要管理优先级,而且它不是monadic。
instance Read Term where
readsPrec _ s =
[(T v False, rest) | (v, '-' : rest) <- reads s] ++
[(T v True , rest) | (v, rest) <- reads s]
对应Show
实例的对称性值得注意:
instance Show Term where
show (T v True) = show v
show (T v False) = show v ++ "-"