我有一个类型
data Value = Int Integer
| Float Double
| Complex (Complex Double)
| ... (other, non-numeric types)
具有关联错误类型
data ValueError = TypeMismatch Value | ... (other constructors)
type ThrowsError = Either ValueError
我想在该类型上实现通用二进制操作,自动强制转换为层次结构中的最高类型,并在其中一个操作数不是数字类型(即函数)的情况下发出错误信号
binaryOp :: Num a => (a -> a -> a) -> Value -> Value -> ThrowsError Value
这样我就可以写,例如,
(binaryOp (+)) (Int 1) (Int 1) ==> Right (Int 2)
(binaryOp (+)) (Int 1) (Float 1.0) ==> Right (Float 2.0)
(binaryOp (+)) (Int 1) (String "1") ==> Left (TypeMismatch (String "1"))
有没有一种简单的方法可以做到这一点?我的第一个想法是定义类似
data NumType = IntType | FloatType | ComplexType
连同功能
typeOf :: Value -> NumType
typeOf (Int _) = IntType
...
promote :: Value -> Value
promote (Int n) = Float (fromInteger n)
promote (Float n) = Complex (n :+ 0)
但我很难让它发挥作用。有什么建议吗?
多一点上下文。我正在编写一个 Scheme 解释器,我想实现 Scheme numeric tower。
事实上,我想要实现比我解释的稍微复杂一些的东西,因为我想要一些适用于任意数量的参数的东西,沿着
binaryOp :: Num a => (a -> a -> a) -> [Value] -> ThrowsError Value
这将用 实现foldl1
,但我觉得如果我能解决更简单的问题,那么我将能够解决这个更复杂的问题。