能否对函数类型进行模式匹配?Haskell语法树处理疑问
问题分析与解决方案
你试图对函数的输入输出行为进行模式匹配的操作,在Haskell中概念上不可行。Haskell的模式匹配仅针对代数数据类型(ADT)的构造器,而函数是抽象的一等公民,没有可被模式匹配的结构——你无法直接通过匹配来判断一个函数接收某个输入后会返回什么值,必须实际调用函数才能得到结果。
为什么你的代码报错?
你写的((InputToBeAddedLater _) -> (IsBool bool))不是合法的Haskell模式。模式只能匹配ADT构造器、变量、通配符或字面量,无法描述函数的行为逻辑。GHC提示的ViewPatterns扩展也无法直接解决“匹配函数行为”的问题,它只是允许你将表达式的结果用于模式匹配,本质上还是需要先执行函数调用。
修正方案
要判断resolveToExp返回的函数能否解析为布尔值,你需要调用该函数并检查返回的Exp a结构。具体实现取决于你的迷你语言设计逻辑:
1. 若函数返回值不依赖输入(如示例中的patently_false)
可以传入任意合法的InputToBeAddedLater值(比如空字符串),然后匹配返回的Exp构造器:
{-# LANGUAGE NoImplicitPrelude #-} data MyException = CantResolveToBool -- Haskell标识符不能包含单引号,此处修正为合法命名 deriving (Show) data InputToBeAddedLater = InputToBeAddedLater String data Exp a = ReturnsBoolFunc String (Exp a) | IsBool Bool | ReturnsExpFunc String (Exp a) resolveToExp :: String -> Exp a -> (InputToBeAddedLater -> Exp a) resolveToExp funcName _ | funcName == "patently_false" = (\_ -> IsBool False) resolveToExp _ _ = (\_ -> ReturnsExpFunc "unknown" (IsBool False)) -- 补充默认分支避免非穷尽警告 resolveToBool :: Exp a -> Either MyException Bool resolveToBool (ReturnsBoolFunc _ (ReturnsExpFunc fn arg)) = let resolved = resolveToExp fn arg -- 传入任意输入,获取函数返回的Exp result = resolved (InputToBeAddedLater "") in case result of IsBool bool -> Right bool _ -> Left CantResolveToBool resolveToBool (IsBool bool) = Right bool -- 处理直接布尔值分支 resolveToBool _ = Left CantResolveToBool -- 处理其他无法解析的分支
2. 若函数返回值依赖输入
如果你的迷你语言要求函数在所有输入下都返回布尔值,你需要遍历所有可能的输入(这在输入空间无限时不可行);如果只需要存在某个输入返回布尔值,则需要明确指定用于测试的输入。这种情况下,可能需要重新设计AST或类型系统,让函数的返回类型信息可被静态检查,而不是动态调用判断。
关于ViewPatterns的使用
如果想让代码更紧凑,可以用ViewPatterns将函数调用嵌入模式中,但核心逻辑还是调用函数:
{-# LANGUAGE ViewPatterns #-} resolveToBool :: Exp a -> Either MyException Bool resolveToBool (ReturnsBoolFunc _ (ReturnsExpFunc fn arg)) | IsBool bool <- resolveToExp fn arg (InputToBeAddedLater "") = Right bool | otherwise = Left CantResolveToBool resolveToBool (IsBool bool) = Right bool resolveToBool _ = Left CantResolveToBool
内容的提问来源于stack exchange,提问作者Chris J Harris
相关产品推荐
相关产品推荐

