Haskell 约束:两个类型变量可与运算符一起使用

Haskell 约束:两个类型变量可与运算符一起使用,haskell,functional-programming,Haskell,Functional Programming,我有以下成功编译和运行的函数: -- Linearly interpolates between two values. That is, it is a function which: -- returns y1 when x = x1 -- returns y2 when x = x2 -- returns a value between y1 and y2 when x1 < x < x2 linearInterp x1 y1 x2 y2 x = (x - x1

我有以下成功编译和运行的函数:

-- Linearly interpolates between two values. That is, it is a function which:
--   returns y1 when x = x1
--   returns y2 when x = x2
--   returns a value between y1 and y2 when x1 < x < x2
linearInterp x1 y1 x2 y2 x =
  (x - x1) * slope + y1
  where slope = (y2 - y1) / (x2 - x1)
但是,正如预期的那样,类型签名会导致编译错误。这是因为编译器无法确定是否可以对任意类型的
a
b
进行算术运算。例如,它不知道你可以将
b
除以
a
,就像我在定义
斜率时所做的那样

有没有一种方法可以编写类型约束,说明“
a/b
是可能的”、“a+b
是可能的”等等?我看到了
Mul
Div
Sum
类型类。但它们似乎没有告诉编译器在两种不同类型上进行算术运算的任何内容


如果你想知道,这对我来说很重要,因为我使用的是维度包。在这个包中,确实可以对不同的类型进行算术运算。例如,您可以调用
linearInterp
,其中type
a
Length Float
,type
b
Velocity Float

,如果我在维度前奏的导入中包装您的代码:

import Prelude ()
import Numeric.Units.Dimensional
import Numeric.Units.Dimensional.Prelude

linearInterp x1 y1 x2 y2 x =
  (x - x1) * slope + y1
  where slope = (y2 - y1) / (x2 - x1)
我推断出这种类型:

linearInterp
  :: (Fractional a, Mul d1 d' d, Div d d1 d') =>
     Dimensional DQuantity d1 a
     -> Dimensional DQuantity d a
     -> Dimensional DQuantity d1 a
     -> Dimensional DQuantity d a
     -> Quantity d1 a
     -> Quantity d a
如果您确实想要这种通用性,那么对于函数来说,这似乎是一种相当合理的类型


Mul
Div
Sum
类型类实际上会告诉编译器在不同类型上进行算术运算,因为它们是多参数类:它们各自采用三个参数,分别表示左参数类型、右参数类型和结果类型。

linearInterp的推断类型是什么?你可以用ghci中的:t或ghc中的-fwarn缺少签名进行检查。实际上,是我自己做的-请参阅下面的答案。谢谢。但我想知道是否可以在linearInterp中添加一个类型声明,以便于阅读并帮助诊断程序员错误。我似乎找不到不产生编译器错误的类型声明。错误总是沿着“无法在表达式a/b中匹配a到b”的路线。您可以精确地添加所推断的类型(可能将类型变量重命名为更具描述性)-您希望更简单吗?啊,我现在明白您的意思了。谢谢
linearInterp
  :: (Fractional a, Mul d1 d' d, Div d d1 d') =>
     Dimensional DQuantity d1 a
     -> Dimensional DQuantity d a
     -> Dimensional DQuantity d1 a
     -> Dimensional DQuantity d a
     -> Quantity d1 a
     -> Quantity d a