我想实现一个简单的RestrictedTypeclass,它有两个函数lowerBound和upperBound,每个函数都接受一个Restricted实例并返回一个Num。
class Restricted r where\n lowerBound :: (Num n) => r -> n\n upperBound :: (Num n) => r -> n\nRun Code Online (Sandbox Code Playgroud)\n我正在尝试使用以下类型创建此类型类的实例OrthogonalClass。
instance Restricted OrthogonalClass where\n lowerBound p = orthogonalLowerBound p\n upperBound p = orthogonalUpperBound p\nRun Code Online (Sandbox Code Playgroud)\n在哪里
\northogonalLowerBound :: (Num a) => OrthogonalClass -> a\northogonalLowerBound Legendre = a\n where a = (-1.0) :: Double\n-- orthogonalLowerBound Hermite = NegInf\nRun Code Online (Sandbox Code Playgroud)\n(-1.0)是 aDouble并且它应该是可接受的返回值,因为 aDouble是 的实例Num。但是,我从编译器中收到以下错误:
Polynomials.hs:20:33: error:\n \xe2\x80\xa2 Couldn't match expected type \xe2\x80\x98a\xe2\x80\x99 with actual type \xe2\x80\x98Double\xe2\x80\x99\n \xe2\x80\x98a\xe2\x80\x99 is a rigid type variable bound by\n the type signature for:\n orthogonalLowerBound :: forall a. Num a => OrthogonalClass -> a\n at Polynomials.hs:19:1-55\n \xe2\x80\xa2 In the expression: a\n In an equation for \xe2\x80\x98orthogonalLowerBound\xe2\x80\x99:\n orthogonalLowerBound Legendre\n = a\n where\n a = (- 1.0) :: Double\n \xe2\x80\xa2 Relevant bindings include\n orthogonalLowerBound :: OrthogonalClass -> a\n (bound at Polynomials.hs:20:1)\n |\n20 | orthogonalLowerBound Legendre = a\n | ^\nRun Code Online (Sandbox Code Playgroud)\n我可以通过更改为来解决此(-1.0)问题(-1)。orthogonalLowerBound但是,当我取消注释matchesHermite和 returns的第二个模式时,这对我没有帮助,它是作为数字实例的NegInf数据类的构造函数。Inf
我的困惑就在这里。ADouble是 a 的实例Num,那么为什么我不能Double在函数中返回 a orthogonalLowerBound?为什么我不能返回 an Infwhich 是 a 的实例Num?
我缺少什么?
\n这是 的完整定义OrthogonalClass,Inf如果您需要更多信息
data OrthogonalClass = Legendre | Laguerre | Hermite | Tchebychev\nRun Code Online (Sandbox Code Playgroud)\n-- Playing around with infinity\ndata Inf = NegInf | PosInf | Undef | Finite deriving (Show)\n\ninstance Num Inf where\n (+) a b = infAdd a b\n (-) a b = infSub a b\n (*) a b = infMult a b\n signum a = infSignum a\n abs a = infAbs a\n fromInteger a = infFromInt a\n\ninfAdd :: Inf -> Inf -> Inf\ninfAdd NegInf NegInf = NegInf\ninfAdd PosInf PosInf = PosInf\ninfAdd PosInf NegInf = Undef\ninfAdd NegInf PosInf = Undef\ninfAdd Undef _ = Undef\ninfAdd _ Undef = Undef\ninfAdd NegInf Finite = NegInf\ninfAdd PosInf Finite = PosInf\ninfAdd Finite Finite = Finite\n\ninfSub :: Inf -> Inf -> Inf\ninfSub NegInf NegInf = Undef\ninfSub PosInf PosInf = Undef\ninfSub PosInf NegInf = PosInf\ninfSub NegInf PosInf = NegInf\ninfSub Undef _ = Undef\ninfSub _ Undef = Undef\ninfSub NegInf Finite = NegInf\ninfSub PosInf Finite = PosInf\ninfSub Finite Finite = Finite\n\ninfMult :: Inf -> Inf -> Inf\ninfMult NegInf NegInf = PosInf\ninfMult PosInf PosInf = PosInf\ninfMult PosInf NegInf = NegInf\ninfMult NegInf PosInf = NegInf\ninfMult Undef _ = Undef\ninfMult _ Undef = Undef\ninfMult NegInf Finite = NegInf\ninfMult PosInf Finite = PosInf\ninfMult Finite Finite = Finite\n\ninfAbs :: Inf -> Inf\ninfAbs NegInf = PosInf\ninfAbs PosInf = PosInf\ninfAbs Undef = Undef\ninfAbs Finite = Finite\n\ninfSignum :: (Num a) => Inf -> a\ninfSignum NegInf = (-1)\ninfSignum PosInf = 1\ninfSignum Undef = 0\ninfSignum Finite = 0\n\ninfFromInt :: (Integral i) => i -> Inf\ninfFromInt x = Finite\nRun Code Online (Sandbox Code Playgroud)\n
这是关于泛型类型方向的一个非常常见的混淆。
简而言之:是函数的调用者选择泛型类型,而不是实现者。
如果您有一个带有此签名的函数:
orthogonalLowerBound :: (Num a) => OrthogonalClass -> a
Run Code Online (Sandbox Code Playgroud)
该签名说:嘿,你,无论谁调用我的函数!选择一种类型。任何类型。我们就这样称呼它吧a。现在确保有一个实例Num a。完毕?伟大的!现在我可以向您返回该类型的值a。
此类型签名是对调用该函数的人的承诺,而您(该函数的实现者)必须履行该承诺。无论调用者选择什么类型,您都必须返回该类型的值。
调用者可以选择任何具有Num实例的类型,例如:
o :: OrthogonalClass
o = ...
x :: Int
x = orthogonalLowerBound o
y :: Decimal
y = orthogonalLowerBound o
Run Code Online (Sandbox Code Playgroud)
解决方案?如果您的函数应该返回 a Double,只需在其类型签名中说明即可:
orthogonalLowerBound :: OrthogonalClass -> Double
Run Code Online (Sandbox Code Playgroud)
当然,在这种情况下,您不能 return Inf,这应该是这样:函数不能根据参数的值返回不同的类型。此功能称为“依赖类型”,Haskell 不直接支持它。
如果您确实需要无穷大,该Double类型也包含它,并且有多种方法可以将其作为值获取。例如从包装上看一下infinityieee754
| 归档时间: |
|
| 查看次数: |
75 次 |
| 最近记录: |