如何在以下非常简单的函数中解决此 class 实例错误?
How can I resolve this class instance error in the following very simple function?
我想实现一个简单的 Restricted
类型 class,它有两个函数,lowerBound
和 upperBound
,每个函数都有一个 Restricted
实例和 return 一个 Num
.
class Restricted r where
lowerBound :: (Num n) => r -> n
upperBound :: (Num n) => r -> n
我正在尝试使用 OrthogonalClass
数据类型创建此类型class 的实例。
instance Restricted OrthogonalClass where
lowerBound p = orthogonalLowerBound p
upperBound p = orthogonalUpperBound p
哪里
orthogonalLowerBound :: (Num a) => OrthogonalClass -> a
orthogonalLowerBound Legendre = a
where a = (-1.0) :: Double
-- orthogonalLowerBound Hermite = NegInf
(-1.0)
是一个 Double
,它应该是一个可接受的 return 值,因为 Double
是 Num
的一个实例。但是,我从编译器中收到以下错误:
Polynomials.hs:20:33: error:
• Couldn't match expected type ‘a’ with actual type ‘Double’
‘a’ is a rigid type variable bound by
the type signature for:
orthogonalLowerBound :: forall a. Num a => OrthogonalClass -> a
at Polynomials.hs:19:1-55
• In the expression: a
In an equation for ‘orthogonalLowerBound’:
orthogonalLowerBound Legendre
= a
where
a = (- 1.0) :: Double
• Relevant bindings include
orthogonalLowerBound :: OrthogonalClass -> a
(bound at Polynomials.hs:20:1)
|
20 | orthogonalLowerBound Legendre = a
| ^
我可以通过将 (-1.0)
更改为 (-1)
来解决这个问题。但是,当我取消注释匹配 Hermite
和 returns NegInf
的第二个模式时,这对我没有帮助,它是数据 [=57 的构造函数=] Inf
这是一个数字的实例。
这是我的困惑。 A Double
是 Num
的一个实例,那么为什么我不能在我的函数 orthogonalLowerBound
中 return a Double
?为什么我不能 return 作为 Num
实例的 Inf
?
我错过了什么?
这是 OrthogonalClass
和 Inf
的完整定义,以备您需要更多信息
data OrthogonalClass = Legendre | Laguerre | Hermite | Tchebychev
-- Playing around with infinity
data Inf = NegInf | PosInf | Undef | Finite deriving (Show)
instance Num Inf where
(+) a b = infAdd a b
(-) a b = infSub a b
(*) a b = infMult a b
signum a = infSignum a
abs a = infAbs a
fromInteger a = infFromInt a
infAdd :: Inf -> Inf -> Inf
infAdd NegInf NegInf = NegInf
infAdd PosInf PosInf = PosInf
infAdd PosInf NegInf = Undef
infAdd NegInf PosInf = Undef
infAdd Undef _ = Undef
infAdd _ Undef = Undef
infAdd NegInf Finite = NegInf
infAdd PosInf Finite = PosInf
infAdd Finite Finite = Finite
infSub :: Inf -> Inf -> Inf
infSub NegInf NegInf = Undef
infSub PosInf PosInf = Undef
infSub PosInf NegInf = PosInf
infSub NegInf PosInf = NegInf
infSub Undef _ = Undef
infSub _ Undef = Undef
infSub NegInf Finite = NegInf
infSub PosInf Finite = PosInf
infSub Finite Finite = Finite
infMult :: Inf -> Inf -> Inf
infMult NegInf NegInf = PosInf
infMult PosInf PosInf = PosInf
infMult PosInf NegInf = NegInf
infMult NegInf PosInf = NegInf
infMult Undef _ = Undef
infMult _ Undef = Undef
infMult NegInf Finite = NegInf
infMult PosInf Finite = PosInf
infMult Finite Finite = Finite
infAbs :: Inf -> Inf
infAbs NegInf = PosInf
infAbs PosInf = PosInf
infAbs Undef = Undef
infAbs Finite = Finite
infSignum :: (Num a) => Inf -> a
infSignum NegInf = (-1)
infSignum PosInf = 1
infSignum Undef = 0
infSignum Finite = 0
infFromInt :: (Integral i) => i -> Inf
infFromInt x = Finite
这是对泛型类型方向的一种非常常见的混淆。
简而言之:选择泛型的是函数的调用者,而不是实现者
如果您有一个具有此签名的函数:
orthogonalLowerBound :: (Num a) => OrthogonalClass -> a
那个签名说:嘿你,谁调用我的函数!选择一个类型。任何类型。我们称它为 a
。现在确保有一个实例 Num a
。完毕?伟大的!现在我可以 return 你一个 a
.
类型的值
此类型签名是对函数调用者的承诺,而您作为函数的实现者必须履行该承诺。无论调用者选择什么类型,您都必须 return 该类型的值。
并且调用者可以选择任何具有 Num
实例的类型,例如:
o :: OrthogonalClass
o = ...
x :: Int
x = orthogonalLowerBound o
y :: Decimal
y = orthogonalLowerBound o
解决办法?如果你的函数应该 return a Double
,只需在它的类型签名中这样说:
orthogonalLowerBound :: OrthogonalClass -> Double
当然,在这种情况下你不能 return Inf
,这是应该的:一个函数不能 return 不同的类型,这取决于参数的值。此功能称为“依赖类型”,Haskell 没有直接支持它。
如果您确实需要无穷大,Double
类型也包含它,并且有多种方法可以将其作为值获取。例如,看看 infinity
from the ieee754
package
我想实现一个简单的 Restricted
类型 class,它有两个函数,lowerBound
和 upperBound
,每个函数都有一个 Restricted
实例和 return 一个 Num
.
class Restricted r where
lowerBound :: (Num n) => r -> n
upperBound :: (Num n) => r -> n
我正在尝试使用 OrthogonalClass
数据类型创建此类型class 的实例。
instance Restricted OrthogonalClass where
lowerBound p = orthogonalLowerBound p
upperBound p = orthogonalUpperBound p
哪里
orthogonalLowerBound :: (Num a) => OrthogonalClass -> a
orthogonalLowerBound Legendre = a
where a = (-1.0) :: Double
-- orthogonalLowerBound Hermite = NegInf
(-1.0)
是一个 Double
,它应该是一个可接受的 return 值,因为 Double
是 Num
的一个实例。但是,我从编译器中收到以下错误:
Polynomials.hs:20:33: error:
• Couldn't match expected type ‘a’ with actual type ‘Double’
‘a’ is a rigid type variable bound by
the type signature for:
orthogonalLowerBound :: forall a. Num a => OrthogonalClass -> a
at Polynomials.hs:19:1-55
• In the expression: a
In an equation for ‘orthogonalLowerBound’:
orthogonalLowerBound Legendre
= a
where
a = (- 1.0) :: Double
• Relevant bindings include
orthogonalLowerBound :: OrthogonalClass -> a
(bound at Polynomials.hs:20:1)
|
20 | orthogonalLowerBound Legendre = a
| ^
我可以通过将 (-1.0)
更改为 (-1)
来解决这个问题。但是,当我取消注释匹配 Hermite
和 returns NegInf
的第二个模式时,这对我没有帮助,它是数据 [=57 的构造函数=] Inf
这是一个数字的实例。
这是我的困惑。 A Double
是 Num
的一个实例,那么为什么我不能在我的函数 orthogonalLowerBound
中 return a Double
?为什么我不能 return 作为 Num
实例的 Inf
?
我错过了什么?
这是 OrthogonalClass
和 Inf
的完整定义,以备您需要更多信息
data OrthogonalClass = Legendre | Laguerre | Hermite | Tchebychev
-- Playing around with infinity
data Inf = NegInf | PosInf | Undef | Finite deriving (Show)
instance Num Inf where
(+) a b = infAdd a b
(-) a b = infSub a b
(*) a b = infMult a b
signum a = infSignum a
abs a = infAbs a
fromInteger a = infFromInt a
infAdd :: Inf -> Inf -> Inf
infAdd NegInf NegInf = NegInf
infAdd PosInf PosInf = PosInf
infAdd PosInf NegInf = Undef
infAdd NegInf PosInf = Undef
infAdd Undef _ = Undef
infAdd _ Undef = Undef
infAdd NegInf Finite = NegInf
infAdd PosInf Finite = PosInf
infAdd Finite Finite = Finite
infSub :: Inf -> Inf -> Inf
infSub NegInf NegInf = Undef
infSub PosInf PosInf = Undef
infSub PosInf NegInf = PosInf
infSub NegInf PosInf = NegInf
infSub Undef _ = Undef
infSub _ Undef = Undef
infSub NegInf Finite = NegInf
infSub PosInf Finite = PosInf
infSub Finite Finite = Finite
infMult :: Inf -> Inf -> Inf
infMult NegInf NegInf = PosInf
infMult PosInf PosInf = PosInf
infMult PosInf NegInf = NegInf
infMult NegInf PosInf = NegInf
infMult Undef _ = Undef
infMult _ Undef = Undef
infMult NegInf Finite = NegInf
infMult PosInf Finite = PosInf
infMult Finite Finite = Finite
infAbs :: Inf -> Inf
infAbs NegInf = PosInf
infAbs PosInf = PosInf
infAbs Undef = Undef
infAbs Finite = Finite
infSignum :: (Num a) => Inf -> a
infSignum NegInf = (-1)
infSignum PosInf = 1
infSignum Undef = 0
infSignum Finite = 0
infFromInt :: (Integral i) => i -> Inf
infFromInt x = Finite
这是对泛型类型方向的一种非常常见的混淆。
简而言之:选择泛型的是函数的调用者,而不是实现者
如果您有一个具有此签名的函数:
orthogonalLowerBound :: (Num a) => OrthogonalClass -> a
那个签名说:嘿你,谁调用我的函数!选择一个类型。任何类型。我们称它为 a
。现在确保有一个实例 Num a
。完毕?伟大的!现在我可以 return 你一个 a
.
此类型签名是对函数调用者的承诺,而您作为函数的实现者必须履行该承诺。无论调用者选择什么类型,您都必须 return 该类型的值。
并且调用者可以选择任何具有 Num
实例的类型,例如:
o :: OrthogonalClass
o = ...
x :: Int
x = orthogonalLowerBound o
y :: Decimal
y = orthogonalLowerBound o
解决办法?如果你的函数应该 return a Double
,只需在它的类型签名中这样说:
orthogonalLowerBound :: OrthogonalClass -> Double
当然,在这种情况下你不能 return Inf
,这是应该的:一个函数不能 return 不同的类型,这取决于参数的值。此功能称为“依赖类型”,Haskell 没有直接支持它。
如果您确实需要无穷大,Double
类型也包含它,并且有多种方法可以将其作为值获取。例如,看看 infinity
from the ieee754
package