从Haskell对象中提取信息

时间:2016-07-14 20:00:45

标签: haskell

我是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;他们错了,但我想解释一下如何处理这类事情。

3 个答案:

答案 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

代替。我不是百分之百确定这是为什么。