首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >读取实例会导致解析错误

读取实例会导致解析错误
EN

Stack Overflow用户
提问于 2012-11-25 18:00:17
回答 2查看 1K关注 0票数 3

我希望实现一个read实例,它使我能够读取一个字符串(例如:"- -“--8-3 -")并构造一个包含这些值的列表。

代码语言:javascript
复制
data Value a = Nul | Val a

showsValue :: (Show a) => Value a -> ShowS
showsValue (Val x) =  ("Value" ++) . shows x
showsValue (Nul)   =  ("Nothing 0" ++)

instance Show a => Show (Value a) where
    showsPrec _ x = showsValue x

instance Read a => Read (Value a) where
    readsPrec _ m = readsMatrix m

readsMatrix :: (Read a) => ReadS (Value a)
readsMatrix ('-':s) = [(Nul, rest) | (' ',rest) <- reads s]
readsMatrix s       = [(Val x,rest)| (x,' ':rest) <- reads s]

在执行此测试之后:

代码语言:javascript
复制
read "- 8 - - 3" :: Value Int

我得到了错误*** Exception: Prelude.read: no parse

我在这里做错什么了?

更新

代码语言:javascript
复制
readsMatrix ('-':s) = [(Nul, dropWhile isSpace s)]
readsMatrix s = [(Val x, dropWhile isSpace rest) | (x,rest) <- reads s]
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-11-25 20:00:24

校正值a的读取

首先,不要费心移除空格,这都是由reads处理的。

代码语言:javascript
复制
readsMatrix :: (Read a) => ReadS (Value a)
readsMatrix ('-':s) = [(Nul, dropWhile (==' ') s)]
readsMatrix s       = [(Val x,rest)| (x,rest) <- reads s] 

您的读取实例现在可以用于单个值:

代码语言:javascript
复制
*Main> read "4" :: Value Int
Value4
*Main> read "-" :: Value Int
Nothing 0

校正值a的读取

但是,您希望将列表以空格分隔,因此,由于这是非标准行为,因此需要编写自定义readList :: :: ReadS [Value a]

代码语言:javascript
复制
instance Read a => Read (Value a) where
    readsPrec _ m = readsMatrix m
    readList s = [(map read.words $ s,"")]

所以现在

代码语言:javascript
复制
*Main> read "- 4 2 - 5" :: [Value Int]
[Nothing 0,Value4,Value2,Nothing 0,Value5]

但不幸的是,

代码语言:javascript
复制
*Main> read "- 4 2 \n- 5 4" :: [Value Int]
[Nothing 0,Value4,Value2,Nothing 0,Value5,Value4]

更糟的是,

代码语言:javascript
复制
*Main> read "- 4 2 \n- 5 4" :: [[Value Int]]
*** Exception: Prelude.read: no parse

读取矩阵

没有简单的方法可以绕过这个问题,因为在readListOfLists类中没有Read,那么为什么不创建一个独立的函数呢?

代码语言:javascript
复制
matrix :: Read a => String -> [[Value a]]
matrix = map read.lines

所以

代码语言:javascript
复制
*Main> matrix "3 4 -\n3 - 6\n4 5 -" :: [[Value Int]]
[[Value3,Value4,Nothing 0],[Value3,Nothing 0,Value6],[Value4,Value5,Nothing 0]]

表演不是我想要的

我认为Show实例对于Value有点误导(Nul没有零,Val不是写的Value)。要么写

代码语言:javascript
复制
data Value a = Nul | Val a  deriving Show

以便它看起来像现在一样,或者定义它来匹配Read实例。

代码语言:javascript
复制
instance Show a => Show (Value a) where
  show Nul = "-"
  show (Val a) = show a
票数 2
EN

Stack Overflow用户

发布于 2012-11-25 19:01:44

在您的readsMatrix函数中,

代码语言:javascript
复制
readsMatrix ('-':s) = [(Nul, rest) | (' ',rest) <- reads s]

这意味着在使用'-'之后,输入字符串的其余部分被传递给

代码语言:javascript
复制
reads :: ReadS Char

但是Read实例Char需要一个单引号括起来的字符,比如'h'

要在结果中获得一个元素(' ',rest),您需要--在它之前的可选空格之后--字符序列'\'' : ' ' : '\'' : whatever。你的预期输入中没有这些。您想要做的是在'-'之后移除空格,所以如果空格是可选的,并且可能有多个字符长,

代码语言:javascript
复制
readsMatrix ('-':s) = [(Nul, dropWhile isSpace s)]

工作(如果换行符、制表符等也被忽略的话)。如果您只想要一个强制空间,模式应该是

代码语言:javascript
复制
readsMatrix ('-':' ':s) = [(Nul, s)]

第二方程

代码语言:javascript
复制
readsMatrix s       = [(Val x,rest)| (x,' ':rest) <- reads s]

可以按原样工作,但要求值后面跟着一个空格,例如,readMatrix "3" :: [(Value Int, [Char])]将返回一个空列表。

我想你也希望有空间可选,所以也许

代码语言:javascript
复制
readsMatrix s = [(Val x, dropWhile isSpace rest) | (x,rest) <- reads s]

是您想要的,但是由于reads忽略了大多数类型的前导空格,

代码语言:javascript
复制
readsMatrix s = [(Val x, rest) | (x, rest) <- reads s]

也许会更好。

但是,在'-'之前,您并没有忽略前面的空格,所以也需要这样做。

也许实现更好地使用

代码语言:javascript
复制
lex :: ReadS String

Prelude中,将字符串拆分为大致遵循Haskell语法的标记。

代码语言:javascript
复制
ghci> lex "(12 + 34)  abc"
[("(","12 + 34)  abc")]

除开括号外,从其余部分中分离出令牌"12"等。

一种可能是使用lex,从而使前导空格被适当忽略

代码语言:javascript
复制
readsMatrix s = do
        (tok, rest) <- lex s
        case tok of
           "-" -> return (Nul, rest)
           _   -> case reads tok of
                    [(x,"")] -> return (Val x, rest)
                    _ -> []

最后,

代码语言:javascript
复制
read "- 8 - - 3" :: Value Int

即使这样也会导致*** Exception: Prelude.read: no parse,因为只有在转换后的令牌后面只有空格时,read才会成功,但是在转换初始'-'之后,在其余的输入中仍然会有四个可转换的令牌。

代码语言:javascript
复制
read "- 8 - - 3" :: [Value Int]

另一方面,应该是成功的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13553794

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档