如果我 beta-reduce 以下運算式:
foldr (mappend . Sum) 1 [2]
= (mappend . Sum) 2 (foldr (mappend . Sum) 1 [])
= (mappend . Sum) 2 1
= mappend (Sum 2) 1
...
查看以下型別:
// mappend (<>) :: Monoid a => a -> a -> a
我們可以看到最后一行有一個型別錯誤,因為常量1應該屬于Monoid類(但它不屬于)。
然而,ghci并沒有抱怨。
為什么該運算式型別檢查?
uj5u.com熱心網友回復:
簡短回答:1被解釋為 a Sum a,所以你的檔案夾型別是:
foldr (mappend . Sum) 1 [2] :: Num a => Sum a
哪里2有型別a,哪里有1型別Sum a。
Sum a是Numifa的一個實體Num,確實,源代碼說 [src]:
newtype Sum a = Sum { getSum :: a }
deriving ( Eq -- ^ @since 2.01
, Ord -- ^ @since 2.01
, Read -- ^ @since 2.01
, Show -- ^ @since 2.01
, Bounded -- ^ @since 2.01
, Generic -- ^ @since 4.7.0.0
, Generic1 -- ^ @since 4.7.0.0
, Num -- ^ @since 4.7.0.0
)
因此,這意味著如果您撰寫一個整型文字,例如1,它可以構造為Sum a對于任何a作為 的實體的a Num,因此1 :: Sum Integer也是Sum 1。
因此,這意味著1您的中foldr有 type Sum a,因此例如:
mappend (Sum 2 :: Sum Integer) (1 :: Sum Integer)
-> Sum (2 1)
-> Sum 3
uj5u.com熱心網友回復:
在Sum 型別的檔案中,您會發現這個說明性實體:
Num a => Num (Sum a)
(當然,它應該在那里是完全合理的 - 不僅是Sum a“道德上相同的型別” a,而且Sum顯然被設計為幾乎只用于數字型別)。
因為像 Haskell 中的數字字面值1可以是類的實體的任何型別Num,所以沒有型別錯誤,mappend (Sum 2) 1因為它是mappend (Sum 2) (Sum 1)由編譯器自動有效地轉換成的。(因為在那種Num情況下Sum a,fromInteger 1將是Sum 1。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/537526.html
標籤:哈斯克尔
上一篇:如何正確實作紅黑樹的幺半群?
下一篇:EqOrd類Haskell資料
