为表达式树实现变态

问题描述

我试图在Haskell中实现如下表达式树:

data ExprTr a b = 
                 Variable a 
                | Constant b 
                | Add (ExprTr a b) (ExprTr a b) 
                | Mul (ExprTr a b) (ExprTr a b)
                deriving (Eq,Show)

我希望能够使用变态方法对其执行操作。

当前,这是我得到的功能:

cataTr f _ _ _ (Variable i) = f i
cataTr f g _ _ (Constant i) = g i
cataTr f g h i (Add e1 e2) = g (cataTr f g h i e1) (cataTr f g h i e2)
cataTr f g h i (Mul e1 e2) = h (cataTr f g h i e1) (cataTr f g h i e2)

但是,每当我尝试使用类型为ExprTr String Integer的表达式时,都会出现编译器错误。例如,运行cataTr id id id id (Var "X")返回以下编译器错误,而不是(Var "X")

Couldn't match type 'Integer' with '[Char]'
    Expected type: 'ExprTr String String'
    Actual type: 'ExprTr String Integer'

我不确定如何继续。此外,我希望您能提出一些建议,例如如何键入cataTr这样的函数,以便以后进行调试。

对于Haskell来说,我还很陌生,所以我想了解如何从“第一原理”着手解决这种情况,而不是使用库来为我自己生成分类。

解决方法

这是预期的行为

您猜错了一个错字,因为您应该使用hi作为函数:

cataTr f _ _ _ (Variable i) = f i
cataTr f g _ _ (Constant i) = g i
cataTr f g h i (Add e1 e2) = h (cataTr f g h i e1) (cataTr f g h i e2)
cataTr f g h i (Mul e1 e2) = i (cataTr f g h i e1) (cataTr f g h i e2)

或更优雅:

cataTr f g h i = go
    where go (Variable i) = f i
          go (Constant i) = g i
          go (Add e1 e2) = h (go e1) (go e2)
          go (Mul e1 e2) = i (go e1) (go e2)

或作为@DanielWagner suggests,带有case表达式:

cataTr f g h i = go
    where go v = case v of
              Variable i -> f i
              Constant i -> g i
              Add e1 e2 -> h (go e1) (go e2)
              Mul e1 e2 -> i (go e1) (go e2)

尽管如此,您不能使用cataTr作为第三和第四参数来调用函数id。这些功能需要两个参数。此外,如果ab不同,则两个第一个参数不能都为id,因为您的fa映射到结果类型,并且gb映射到结果类型。

例如,您可以通过以下方式传递数据构造函数以构造标识函数:

cataTr Variable Constant Add Mul (Variable "X")

因此,这将再次产生Variable "X",或者您可以使用Variable将所有0映射到const 0,并使用id,{{ 1}}和(+)来评估表达式:

(*)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...