Parsing 理解读取实例
我对我的数据进行了Parsing 理解读取实例,parsing,haskell,Parsing,Haskell,我对我的数据进行了Read和Show实例,但不理解Read实例 data Tests = Zero | One Int | Two Int Double instance Show Tests where show Zero = "ZERO" show (One i) = printf "ONE %i" i show (Two i j) = printf "TWO %i %f" i j instance Read Tests
Read
和Show
实例,但不理解Read
实例
data Tests = Zero
| One Int
| Two Int Double
instance Show Tests where
show Zero = "ZERO"
show (One i) = printf "ONE %i" i
show (Two i j) = printf "TWO %i %f" i j
instance Read Tests where
readsPrec _ str = [(mkTests str, "")]
mkTests :: String -> Tests
mkTests = check . words
check :: [String] -> Tests
check ["ZERO"] = Zero
check ["ONE", i] = One (read i)
check ["TWO", i, j] = Two (read i) (read j)
check _ = error "no parse"
main :: IO ()
main = do
print Zero
print $ One 10
print $ Two 1 3.14
let x = read "ZERO" :: Tests
print x
let y = read "ONE 2" :: Tests
print y
let z = read "TWO 2 5.5" :: Tests
print z
这是输出
ZERO
ONE 10
TWO 1 3.14
ZERO
ONE 2
TWO 2 5.5
以下是问题:
读取实例
Read
类的最小完整定义是readsPrec | readPrec
和readPrec::readPrec编写的描述
建议使用新型解析器(仅限GHC)替换readsPrec
- 我应该使用
readPrec
吗?如何使用?我在网上找不到任何我能理解的例子
- 什么是
新型解析器
,它是parsec
Int
参数用于什么Show
中派生Read
派生(Show,Read)
来完成大部分工作。但这次我想进入下一个阶段
- readPrec是GHC提供的一种基于解析器组合器的简单方法。如果您愿意为您的Read实例牺牲可移植性,那么您可以使用它,这会使解析变得更容易
- 我在下面提供了一个如何使用readPrec的小示例
- parsec与readPrec不同,但两者都类似于解析器组合器。是一个更完整的解析器库。另一个解析器组合器库是,它的工作原理与parsec非常类似
- parsec和AttorParsec不能与普通的ReadTypeClass一起使用(至少是直接使用),但它们提供的更大的灵活性使它们在需要更复杂的解析时成为一个好主意
readsPrec
的Int
参数用于解析时处理优先级。当您想要解析算术表达式时,这可能很重要。如果优先级高于当前运算符的优先级,则可以选择解析失败Show
派生Read
是不可能的ReadPrec
实现Read
ReadPrec示例:
instance Read Tests where
readPrec = choice [pZero, pOne, pTwo] where
pChar c = do
c' <- get
if c == c'
then return c
else pfail
pZero = traverse pChar "ZERO" *> pure Zero
pOne = One <$> (traverse pChar "ONE " *> readPrec)
pTwo = Two <$> (traverse pChar "TWO " *> readPrec) <*> readPrec
实例读取测试,其中
readPrec=选择[pZero,pOne,pTwo]其中
pChar c=do
对于这样一个简单的语法,推荐一个功能齐全的解析器有点傻(就像推荐用机关枪捕鸟一样)。没有规则规定Show
/Read
不能用于自定义语法(实际上,任何带有Show
实例的抽象类型都必须使用自定义语法)。无法用于实现自定义语法的是派生实例,但OP声明它们未使用派生实例。如果您回答1,我将编辑为问题编号。
您能提供工作代码吗?