Haskell:修复函数中的非执行模式

use*_*080 3 haskell non-exhaustive-patterns

我有一个程序遍历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)))))
Run Code Online (Sandbox Code Playgroud)

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

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

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

提前致谢!

Jef*_*rka 5

那么,当你看到那个定义时Exp,你可以看到有一大堆可能的构造函数.但是在你的功能中,你只需要检查其中的两个.

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

fromExp :: Exp -> String 
fromExp (Var qn)   = fromQName qn
fromExp (Paren e1) = "()"
fromExp _          = "Not defined yet"
Run Code Online (Sandbox Code Playgroud)

这样,如果您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))
Run Code Online (Sandbox Code Playgroud)

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