I am trying to implement an expression tree in Haskell as follows:
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)
And I would like to be able to implement operations on it using a catamorphism.
Currently, this is the function I got:
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)
However, whenever I try to use it with an expresion of type ExprTr String Integer
I get compiler errors. For example, running cataTr id id id id (Var "X")
returns the following compiler error instead of (Var "X")
.
Couldn't match type 'Integer' with '[Char]'
Expected type: 'ExprTr String String'
Actual type: 'ExprTr String Integer'
I am not sure how to proceed. Furthermore, I would appreciate some suggestions on how to type such a function as cataTr to make it easier to debug later.
As I am fairly new to Haskell, I would like to understand how to approach such situations from 'first principles' instead of using a library to generate the catamorphism for myself.
This is expected behavior.
You made a typo in the question I guess, since you should use
h
andi
as functions:or likely more elegant:
or as @DanielWagner suggests, with a
case
expression:Nevertheless, you can not call the function
cataTr
withid
as third and fourth parameter. These functions require two parameters. Furthermore ifa
andb
are different the two first parameters can not be bothid
, since yourf
maps ana
to the result type, and theg
maps ab
to the result type.You can for example pass the data constructor to construct an identity function with:
this will thus yield
Variable "X"
again, or you can for example map allVariable
s to0
withconst 0
, and useid
,(+)
and(*)
to evaluate an expression: