簡體   English   中英

Haskell將Integer轉換為Int

[英]Haskell cast Integer to Int

為什么第一個是正確的而第二個不是? 我想以第二種方式實現代碼,這樣我就不必每次都從Intete中調用,但我不明白如何...

正確

bits :: Integer -> Int 
bits 0 = 0
bits n = fromInteger n `mod` 2 + bits(fromInteger n `div` 2) 

不正確

bits :: Integer -> Int 
bits 0 = 0
bits n = let m = fromInteger n in m `mod` 2 + bits(m `div` 2) 

因為第二次通話你不需要它:

bits :: Integer -> Int 
bits 0 = 0
bits n = fromInteger n `mod` 2 + bits (n `div` 2) 

第二個fromInteger再次導致Integer ,由參數強制為bits

以下是此版本未進行類型檢查的原因:

bits :: Integer -> Int
bits 0 = 0
bits n = let m = fromInteger n in m `mod` 2 + bits(m `div` 2)

首先,請注意m的第一次使用要求mInt因為bits調用的結果必須是Int ,這意味着加法的左側(即m `mod` 2 )必須是Int 為什么是這樣? 嗯,這是因為+運算符的簽名是:

(+) :: (Num a) => a -> a -> a

這要求+兩個參數與其結果具有相同的類型。 類似地,因為m `mod` 2必須是Int ,所以`mod`調用的`mod` (即m )必須是Int ,因為mod有簽名:

mod :: (Integral a) => a -> a -> a

所以,這就是m的第一次使用需要m :: Int 呼!

出於同樣的原因, m第二種用法要求mInteger 這是因為參數bits在表達式bits (m `div` 2)必須是一個Integer ,其要求的左手側`div`操作者必須是一個Integer

因此,我們要求m既是Int又是Integer 這不一定是個問題。 如果你寫了:

bits :: Integer -> Int
bits 0 = 0
bits n = m `mod` 2 + bits(m `div` 2)
  where m :: (Integral a) => a
        m = fromInteger n

並且給定m一個顯式的多態類型簽名,那么m可以同時用作IntInteger 然而,由於稱為單形態限制的東西,沒有明確的類型簽名, m需要具有單個非多態(即,單態類型)。 如果添加pragma:

{-# LANGUAGE NoMonomorphismRestriction #-}

到你的文件的頂部,然后原始定義typechecks罰款:

{-# LANGUAGE NoMonomorphismRestriction #-}

bits :: Integer -> Int
bits 0 = 0
bits n = let m = fromInteger n in m `mod` 2 + bits(m `div` 2)

但是其他人已經注意到,你實際上並不需要在兩個地方使用fromInteger ; 並且同時使用IntInteger是不必要的,並且使用具有約束的單個整數類型( Integral a可能更好。

此外,如果您希望此功能用於實際工作而不僅僅是練習,那么它已經在模塊Data.Bits作為popCount Data.Bits

您可能稍微調整一下簽名並擺脫所有fromInteger s。

bits :: Integral a => a -> a 
bits 0 = 0
bits n = n `mod` 2 + bits (n `div` 2)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM