3

我有一个程序,它遍历 AST 并返回使用的函数和变量的映射以及它们发生的次数。这里是:

import Data.Map
import Language.Haskell.Exts.Syntax

increment :: Ord a => a -> Map a Int -> Map a Int
increment a = insertWith (+) a 1

fromName :: Name -> String
fromName (Ident s) = s
fromName (Symbol st) = st

fromQName :: QName -> String
fromQName (Qual _ fn) = fromName fn
fromQName (UnQual n) = fromName n

fromLiteral :: Literal -> String
fromLiteral (Int int) = show int

fromQOp :: QOp -> Map String Int
fromQOp (QVarOp qn) = increment (fromQName qn) empty

fromExp :: Exp -> String 
fromExp (Var qn) = fromQName qn
fromExp (Paren e1) = "()"

vars :: Exp -> Map String Int
vars (Var qn) = increment (fromQName qn) empty
vars (Lit l) = increment (fromLiteral l) empty
vars (Paren e1) = increment "()" (vars e1) 
vars (InfixApp exp1 qop exp2) = increment (fromExp exp1) $ unionWith (+) (fromQOp qop) (vars exp2)

t3 = (InfixApp (Var (UnQual (Ident "x"))) (QVarOp (UnQual (Symbol "+"))) (Paren (InfixApp (Lit (Int 3)) (QVarOp (UnQual (Symbol "+"))) (Lit (Int 2)))))

该程序在大多数情况下运行甚至工作,但是当我使用“Paren”(如 t3)在 AST 上调用“vars”时,我收到以下错误:

fromList *** Exception: parsemap.hs:(22,1)-(23,25): Non-exhaustive patterns in function fromExp

我不确定如何解决这个问题,我可以使用一些帮助。顺便说一句,我正在使用的构造函数可以在http://hackage.haskell.org/packages/archive/haskell-src-exts/1.0.1/doc/html/Language-Haskell-Exts-Syntax.html找到#t:Exp 以防万一。

提前致谢!

4

1 回答 1

5

好吧,当您查看 的定义时Exp,您会看到有一大堆可能的构造函数。但是在您的功能中,您只检查其中两个。

那么如果我打电话fromExp (Lit l)怎么办?这是未定义的,这不好。解决此问题的最简单方法是添加一个涵盖所有其他可能构造函数的案例:

fromExp :: Exp -> String 
fromExp (Var qn)   = fromQName qn
fromExp (Paren e1) = "()"
fromExp _          = "Not defined yet"

这样,如果您fromExp使用任何其他构造函数调用,它将返回"Not defined yet".


在这种特定情况下,评估是:

vars t3
=> vars (InfixApp (Var (UnQual (Ident "x"))) (QVarOp (UnQual (Symbol "+"))) (Paren (InfixApp (Lit (Int 3)) (QVarOp (UnQual (Symbol "+"))) (Lit (Int 2)))))
=> vars (Paren (InfixApp (Lit (Int 3)) (QVarOp (UnQual (Symbol "+"))) (Lit (Int 2)))))
=> vars (InfixApp (Lit (Int 3)) (QVarOp (UnQual (Symbol "+"))) (Lit (Int 2))))
=> fromExp (Lit (Int 3))

并且没有fromExp (Lit l)定义来评估该表达式。

于 2013-08-01T17:27:50.977 回答