簡體   English   中英

了解Haskell中的類型

[英]Understanding types in Haskell

我正在嘗試將函數h映射到素數列表。 兩者都在下面給出:

f k x = floor ( log k / log x )

h = f 20

primes = 2 : sieve [3,5..]
  where
    sieve (p:xs) = p:[ x | x <- xs, x `mod` p > 0 ]

但是,當我嘗試map h primes ,出現以下錯誤:

Ambiguous type variable `a0' in the constraints:
  (Enum a0)
    arising from the arithmetic sequence `3, 5 .. '

等等...

函數f和素數似乎都能按預期工作,但我無法將f應用於素數中的數字??? 我在這里誤會什么?

您的函數primes是類型[Integer]

您的函數hDouble -> Integer類型的。

map的類型如下:

ghci> :t map
map :: (a -> b) -> [a] -> [b]

或者,當專門處理Integer列表時,其類型簽名將變為:

map :: (Integer -> b) -> [Integer] -> [b]

但是要傳遞給map h函數的類型為Double- Double -> Integer ,因此不會進行類型檢查,因為它期望的是Integer- Integer -> b而不是接受Double的函數。

始終嘗試在功能之前編寫類型簽名,這將使您的生活更輕松。

問題

primes :: Integral a => [a]h :: (RealFrac a, Integral b, Floating a) => a -> b 現在,沒有任何類型同時是RealFracIntegral實例,但是GHC不知道這一點,因此它給出的錯誤消息有點令人困惑。

原因

log :: Floating a => a -> a floor :: (RealFrac a, Integral b) => a -> b log :: Floating a => a -> a(/) :: Fractional a => a -> a -> a floor :: (RealFrac a, Integral b) => a -> b (/) :: Fractional a => a -> a -> a floor :: (RealFrac a, Integral b) => a -> b (/) :: Fractional a => a -> a -> afloor :: (RealFrac a, Integral b) => a -> b ,所以當我們撰寫他們我們得到上面的類型簽名。 Haskell具有強大的數字類型,這意味着整數和浮點類型之間沒有隱式轉換。

解決方案

使用顯式轉換函數fromIntegral :: (Integral a, Num b) => a -> b

map (h . fromIntegral) primes

primes有什么類型? 那完全取決於情況。 它可能是

primes :: [Integer]

或者是其他東西。 目前尚不清楚,因為像3這樣的文字的類型為3 :: Num a => a 我們唯一可以確定的是,無論它是Enum的實例是什么,否則[3,5..]將無法工作。

現在f是什么類型? f使用log作為參數,然后對結果取底,因此我們可以期待類似

f :: (RealFrac a, Floating a, Integral b) => a -> a -> b

但是,這已經暗示您不能將其與map一起使用,因為map需要將(a -> b) a- (a -> b)作為第一個參數。 更重要的是, primes元素不滿足Floating約束:

*Main> let (p1:p2:_) = primes
*Main> f p1 p2

<interactive>:29:1:
    No instance for (RealFrac Integer) arising from a use of `f'
    Possible fix: add an instance declaration for (RealFrac Integer)
    In the expression: f p1 p2
    In an equation for `it': it = f p1 p2

因此,我們需要更改primes類型或f的類型。 我們更改f的類型:

f k x = floor ( log (fromIntegral k) / log (fromIntegral x) )

現在我們可以按預期使用f p1 p2

*Main> let (p1:p2:_) = primes
*Main> f p1 p2
0

但是map問題呢? map期望(a -> b) a- (a -> b)作為第一個參數,而f仍然是(a -> b -> c) *。 從您當前的代碼看來,您似乎想使用兩個連續的素數並應用f 為此,我們首先使用uncurry

uncurry :: (a -> b -> c) -> (a, b) -> c

現在, uncurry f具有(a, b) -> c 但是現在列表(質primes )不再是配對列表。 但是,我們可以很容易地解決此問題,我們用尾部zip素數:

map (uncurry f) (zip primes $ tail primes)

這樣便可以在單個列表的連續元素上映射具有兩個參數的函數。


* k或x可以是不同的積分類型

暫無
暫無

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

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