我定義了一個函式來計算sqrt和轉換Integral類的引數:
isqrt :: Integral i => i -> i
isqrt = floor . sqrt . fromIntegral
我不明白為什么會編譯。如果我們寫出各個函式的簽名,我們會得到:
fromIntegral :: (Num b, Integral a) => a -> b
sqrt :: Floating a => a -> a
floor :: (RealFrac a, Integral b) => a -> b
所以 " sqrt" 需要某種Floating型別的東西,但它提供了Num. 如果您查看類層次結構,您可以看到它Floating“繼承”了Num但不是相反。我會理解是否Floating可以隱式處理,Num因為它是一種更“專業”的型別。為什么這對編譯器沒問題?
uj5u.com熱心網友回復:
所以
sqrt需要某種Floating型別的東西,但它提供了Num.
沒有。將fromIntegral它轉換成可以保證任何數量與型別是的成員Integral型別類到任何 Num型別的,而不是一個 Num型別。
由于sqrt需要一個屬于Floating型別類成員的數字,對于這種特定情況,fromIntegral將特別回傳屬于型別Floating類成員的型別。
uj5u.com熱心網友回復:
不,sqrt不提供任何Num.
它的供應商fromIntegral確實能夠Num根據需要生產任何東西,而sqrt 需求aFloating作為其輸入。而且Floating是一個子類的Num。
于是fromIntegral愉快地答應了。因為它可以產生 any Num,所以它肯定可以在其子類中產生任何型別。因此,無論它最終是什么特定的具體型別,它都在 中Floating,并且必然在 中Num。
因此fromIntegral提供它沒有問題。
編輯: Floating不是一種型別。它是一型別別。具體型別可能Floating屬于型別類。由于Floating是 的子類Num,因此也保證此型別別在Num. 這不是由于您提到的“繼承”而自動發生的事情。“繼承”即子類關系是對該特定型別的要求,該型別Floating也將(在)Num即實作其方法以及來自Floating.
所以是的,(特定的,具體的)Floating型別也可以被視為一種Num型別。
另一方面,sqrt產生與其輸入型別相同的型別,因此它將是相同的具體Floating型別。但floor期望一個RealFrac型別。
觀察
> :t floor ----------
floor :: (Integral b, RealFrac a) => a -> b
> :t sqrt . fromIntegral ----------
sqrt . fromIntegral :: (Integral a, Floating c) => a -> c
> :t floor . sqrt ---------- ----------
floor . sqrt :: (Integral c, RealFrac b, Floating b) => b -> c
> :i Floating
class Fractional a => Floating a where
....
instance Floating Float
instance Floating Double
> :i RealFrac
class (Real a, Fractional a) => RealFrac a where
....
instance RealFrac Float
instance RealFrac Double
因此,該sqrt呼叫生成(并因此接受)的具體型別必須是 (in)RealFrac以及Floating.
由于它不是從該應用程式鏈的外部觀察到的,它可以是任何兼容型別,因此是不明確的;但是輸入 defaulting 并選擇Double,除非您更改了默認值。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/350108.html
上一篇:二叉樹的最小值
下一篇:通用型別(地圖。過濾器)
