我有一个程序,它遍历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以防有帮助。
提前感谢!
当你查看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))
并且没有CCD_ 5定义来评估该表达式。