我在完成要创建使用广义折叠函数评估布尔AST的函数的任务时遇到了麻烦。我将向您展示一些示例进行说明。
首先,给出一个我想要的示例,但对于一个将整数相加的AST:
data Expr = Val Int | Add Expr Expr deriving Show
folde :: (Int -> a) -> (a -> a -> a) -> Expr -> a
folde f g (Val x) = f x
folde f g (Add x y) = g (folde f g x) (folde f g y)
eval :: Expr -> Int
eval expr = folde (\x -> x) (\x y -> x + y) expr
这很好。
现在是布尔AST和折叠功能:
data Bexp = T | F | And Bexp Bexp | Or Bexp Bexp deriving (Ord, Eq)
foldb :: a -> a -> (a -> a -> a) -> (a -> a -> a) -> Bexp -> a
foldb t f a o T = t
foldb t f a o F = f
foldb t f a o (And x y) = a (foldb t f a o x) (foldb t f a o y)
foldb t f a o (Or x y) = o (foldb t f a o x) (foldb t f a o y)
我遇到的麻烦是,创建了一个与上述简单AST的eval函数相同的函数,也就是说,使用带有一些lambda的foldb函数来评估Bexp
表达式是T
还是F
。
我不明白为什么这个功能不起作用:
evb :: Bexp -> Bool
evb bexp = foldb (\_ -> True) (\_ -> False) (\x y -> x == T && y == T) (\x y -> x == T || y == T) bexp
由于类型错误,GHCi甚至不想编译它。
提前致谢。
如果想在最后使用foldb
a Bool
,则需要选择a = Bool
其类型。所以,我们现在正在使用
foldb :: Bool
-> Bool
-> (Bool -> Bool -> Bool)
-> (Bool -> Bool -> Bool)
-> Bexp
-> Bool
因此,这foldb (\_->True) (\_->False) ...
是错误的,因为前两个参数必须是布尔值,而不是函数。我们需要类似的东西foldb True False ...
。接下来的两个参数必须是布尔型二进制运算符,例如\x y -> x && y
,可以(&&)
简写为。
我们终于得到:
evb :: Bexp -> Bool
evb bexp = foldb True False (&&) (||)