我想實作一個簡單的RestrictedTypeclass,它有兩個函式,lowerBound每個upperBound函式都接受一個Restricted實體并回傳一個Num.
class Restricted r where
lowerBound :: (Num n) => r -> n
upperBound :: (Num n) => r -> n
我正在嘗試使用OrthogonalClass資料型別創建此型別類的實體。
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)是 aDouble并且它應該是一個可接受的回傳值,因為 aDouble是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)。orthogonalLowerBound但是,當我取消注釋matchHermite和 returns的第二個模式時,這對我沒有幫助,它是作為數字實體的NegInf資料類的建構式。Inf
這就是我的困惑。ADouble是 a 的一個實體Num,那么為什么我不能Double在我的函式中回傳 aorthogonalLowerBound呢?為什么我不能回傳一個Infwhich 是 a 的實體Num?
我錯過了什么?
這是完整的定義,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
uj5u.com熱心網友回復:
這是關于泛型型別方向的一個非常常見的混淆。
簡而言之:選擇泛型型別的是函式的呼叫者,而不是實作者。
如果您有具有此簽名的函式:
orthogonalLowerBound :: (Num a) => OrthogonalClass -> a
那個簽名說:嘿你,誰呼叫我的函式!選擇一種型別。任意種類。讓我們稱之為a。現在確保有一個實體Num a。完畢?偉大的!現在我可以回傳一個該型別的值a。
這種型別簽名是對呼叫該函式的任何人的承諾,而您,該函式的實作者,必須履行該承諾。無論呼叫者選擇何種型別,您都必須回傳該型別的值。
呼叫者可以選擇任何具有Num實體的型別,例如:
o :: OrthogonalClass
o = ...
x :: Int
x = orthogonalLowerBound o
y :: Decimal
y = orthogonalLowerBound o
解決方案?如果您的函式應該回傳 a Double,只需在其型別簽名中說明:
orthogonalLowerBound :: OrthogonalClass -> Double
當然,在這種情況下你不能 return Inf,這應該是:一個函式不能根據引數的值回傳不同的型別。這個特性被稱為“依賴型別”,Haskell 沒有直接支持它。
如果您確實需要無窮大,則該Double型別也確實包含它,并且有多種方法可以將其作為值獲取。例如,infinity從ieee754包裝上看
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/412890.html
標籤:
