如何为二进制运算符定义类型类?

时间:2018-09-10 01:33:57

标签: haskell

这是一个仅对数字求和的计算器:

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是运算符而不是操作数。

我该怎么做?

1 个答案:

答案 0 :(得分:4)

您的evaluate函数可以只是

evaluate :: Expr -> Int
evaluate (Value x) = x
evaluate (Plus x y) = evaluate x + evaluate y

所有情况均已考虑。

对于每个类型类,您不能为Plus创建一个实例,因为它是一个构造函数,并且您需要为类型指定实例(在这种情况下,Expr是类型,而PlusValue是构造函数)。如果您想要一个带有两个特定类型元素并生成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