我是Haskell的新手,我对如何从功能结果中获取值感到困惑。在我的特定情况下,我试图解析Haskell文件并查看哪些AST节点出现在哪些行上。这是我到目前为止的代码:
import Language.Haskell.Parser
import Language.Haskell.Syntax
getTree :: String -> IO (ParseResult HsModule)
getTree path = do
file <- readFile path
let tree = parseModuleWithMode (ParseMode path) file
return tree
main :: IO ()
main = do
tree <- getTree "ex.hs"
-- <do something with the tree other than print it>
print tree
所以在我有评论的行上,我有一个语法树tree
。它似乎有ParseResult HsModule
类型。我想要的只是HsModule
。我想我正在寻找的功能如下:
extract :: ParseResult a -> a
或者更好的是,一般的Haskell函数
extract :: AnyType a -> a
也许我在这里错过了关于Haskell的一个主要概念?
P.S。我理解将这些事情视为&#34;对象&#34;并尝试访问&#34; Fields&#34;他们错了,但我想解释一下如何处理这类事情。
答案 0 :(得分:7)
寻找类型
的一般功能extract :: AnyType a -> a
确实对Haskell表现出很大的误解。考虑AnyType
可能包含的许多内容,以及如何从中提取一个对象。那么Maybe Int
呢?您可以轻松地将Just 5
转换为5
,但是您应该为Nothing
返回多少个数字?
或者如果AnyType
是[]
,那么您有[String]
?
extract ["help", "i'm", "trapped"]
或
extract []
ParseResult
有类似的&#34;问题&#34;,因为它使用ParseOk
包含表示一切正常的结果,并ParseFailed
表示错误。如果解析成功,则不完整的模式匹配会成功获得结果,但如果实际上解析失败,则会使程序崩溃。通过使用ParseResult
,Haskell鼓励你考虑如果你正在分析的代码没有正确分析你应该做什么,而不是只是轻易地假设它会很好。
答案 1 :(得分:3)
ParseResult
的定义是:
data ParseResult a = ParseOk a | ParseFailed SrcLoc String
(从源代码获得)
因此有两种可能性:解析成功,并且它将返回一个ParseOk
实例,或者在解析过程中出现错误,在这种情况下,您将获得错误的位置,并显示错误消息ParseFailed
构造函数。
所以你可以定义一个函数:
getData :: ParseResult a -> a
getData (ParseOk x) = x
getData (ParseFailed _ s) = error s
最好再抛出一个错误,因为你的编译器/解释器/ analyzer / ...总是可能解析包含语法错误的Haskell程序。
答案 2 :(得分:1)
我刚想出如何做到这一点。似乎当我试图定义
时extract :: ParseResult a -> a
extract (ParseResult a) = a
我实际上需要使用
extract :: ParseResult a -> a
extract (ParseOk a) = a
代替。我不是百分之百确定这是为什么。