作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在 this answer , 人们发现执行 Read
不会很困难的声明数据类型 Tree
的实例,实际解析已经完成。
但是,我很难理解 read
这样的功能是如何实现的。作品:AFAIK,我应该实现 readsPrec
函数而不是 read
这个readsPrec
应该对仅包含一个字符的字符串执行读取。这个对吗?
如果是这样,那么应该如何实现 Read
Tree
的实例当通过 ParsecT
完成解析时?我们可以逐字打破解析,还是有必要这样做?
没想到read
作为 Haskell 中的一个困难功能,但现在我发现它非常困惑和困惑,我在搜索中迷失了 Hoogle
对于 readP_to_S
等所有不熟悉的事物, readS
, ETC。
任何帮助或引用将不胜感激。
最佳答案
我一直在想这个问题,你的问题促使我研究它。
摘要:最简单的手动操作方法:
instance Read Tree where
readsPrec _ str = [(parsecRead str,"")]
deriving
是更安全的选择;以上不适用于
[Tree]
和其他数据类型。我的理解是
Show
和
Read
是
不打算手动实现 ;他们
应派生并在
上工作语法正确的 Haskell 表达式 .
Read
的原因不是那么简单
class Read a where
read :: String -> a
Read
的最小完整实现是
readsPrec
或
readPrec
.后者被描述为“建议使用新式解析器替换 readsPrec(仅限 GHC)”。这对我来说有点麻烦,所以让我们开始实现
readsPrec
.
readsPrec :: Read a => Int -> ReadS a
type ReadS a = String -> [(a,String)]
ReadS
的文档读取“类型
a
的解析器,表示为接受
String
并返回可能解析列表为
(a,String)
对的函数”。对我来说,“解析”是什么并不完全清楚,但看看
source code for read
in Text.Read
揭示:
read :: Read a => String -> a
read s = either errorWithoutStackTrace id (readEither s)
readEither :: Read a => String -> Either String a
readEither s =
-- minPrec is defined as 0 in Text.ParserCombinators.ReadPrec
case [ x | (x,"") <- readPrec_to_S read' minPrec s ] of
[x] -> Right x
[] -> Left "Prelude.read: no parse"
_ -> Left "Prelude.read: ambiguous parse"
where
read' = -- read' :: P.ReadPrec a
do x <- readPrec
lift P.skipSpaces -- P is Text.ParserCombinators.ReadP
return x
readPrec_to_S
的定义等等,但我觉得不值得。我认为定义清楚地表明我们应该返回
[(x,"")]
作为一个成功的解析。
readsPrec
的整数参数似乎是“优先上下文”。我的猜测是,如果我们只想一次解析一棵树,忽略它是安全的,但是如果我们尝试解析
[Tree]
的实例,忽略它会导致问题。例如。我会忽略它,因为我认为这不值得麻烦。
parsecRead :: String -> Tree
如您所指的帖子中所定义(作者称之为
read'
)
instance Read Tree where
readsPrec _ str = [(parsecRead str,"")]
Show
实例):
main = do
print (read "ABC(DE)F" == example)
print ([read "ABC(DE)F", read "ABC(DE)F"] :: [Tree])
print (read "[ABC(DE)F,ABC(DE)F]" :: [Tree])
True
[ABC(DE)F,ABC(DE)F]
Test.hs: Prelude.read: no parse
deriving (Read)
实际上是唯一安全的选择,除非您愿意深入了解优先级的细节。
Show
和
Read
实际上是
主要意在派生 ,并且这些字符串应为
语法正确的 Haskell 表达式 (如果我错了,请纠正我)。对于更一般的解析,
Parsec
等库可能是更好的选择。
Text.Read
GHC.Read
Text.ParserCombinators.ReadP
Text.ParserCombinators.ReadPrec
关于haskell - 如何在 Haskell 中实现实际解析已经完成的 Read 实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38815948/
我是一名优秀的程序员,十分优秀!