这是一个仅对数字求和的计算器:
module Data.Calculator where
data Expr = Plus Expr Expr | Value Int
evaluate :: Expr -> Int
evaluate (Value a) = a
evaluate (Plus (Value a) (Value b)) = a + b
evaluate (Plus (Plus left right) (Value b)) = (evaluate left) + (evaluate right) + b
evaluate (Plus (Value a) (Plus left right)) = a + (evaluate left) + (evaluate right)
evaluate (Plus a@(Plus left right) b@(Plus left' right')) = (evaluate a) + (evaluate b)
evaluate
函数似乎很冗长。理想情况下,我想同时定义两个运算符的类型类,然后将Plus
定义为运算符的实例,如下所示:
class BinaryOp a where
apply :: a -> a -> Expr
instance BinaryOp Plus where
apply x y = x + y
但这显然不起作用,因为定义a
的类型BinaryOp
是运算符而不是操作数。
我该怎么做?
答案 0 :(得分:4)
您的evaluate
函数可以只是
evaluate :: Expr -> Int
evaluate (Value x) = x
evaluate (Plus x y) = evaluate x + evaluate y
所有情况均已考虑。
对于每个类型类,您不能为Plus
创建一个实例,因为它是一个构造函数,并且您需要为类型指定实例(在这种情况下,Expr
是类型,而Plus
和Value
是构造函数)。如果您想要一个带有两个特定类型元素并生成Int
的类型类,则可以编写如下内容:
data Expr = Plus Expr Expr | Value Int
class BinaryOp a where
apply :: a -> a -> Int
instance BinaryOp Expr where
apply x y = evaluate $ Plus x y