2016-07-22 53 views
4

我有以下函數返回雙因子對於給定數目曖昧類型變量'A0' 從使用`產生它

factorPairs:: (RealFrac a, Floating a, Integral a) => a -> [(a, a)] 
factorPairs n = map(\x -> (x, div n x)) [y | y <- [1..(ceiling $ sqrt n)], n `rem` y == 0] 

當我打電話了ghci factorPairs 18功能我得到的

* Ambiguous type variable `a0' arising from a use of `it' 
     prevents the constraint `(Floating a0)' from being solved. 
     Probable fix: use a type annotation to specify what `a0' should be. 
     These potential instances exist: 
     instance Floating Double -- Defined in `GHC.Float' 
     instance Floating Float -- Defined in `GHC.Float' 
    * In the first argument of `print', namely `it' 
     In a stmt of an interactive GHCi command: print it 

運行時錯誤我也很難在ghci中

map(\x -> (x, div 18 x)) [y | y <- [1..(ceiling $ sqrt 18)], 18 `rem` y == 0] 代碼中的函數,並且沒有任何問題,但我似乎無法找出爲什麼我的功能失敗。我相信ghci試圖告訴我,它不能找出什麼類型呼籲print與但我正在努力尋找解決方案。

+0

嘗試「:t map(\ x - >(x,div 18 x))[y | y < - [1 ..(ceiling $ sqrt 18)],18'rem' y == 0 ]「在GHCi上找出推斷的類型。 – Mephy

+1

你應該重新考慮你的類型簽名。你能說出一個既是「浮動」又是「積分」的類型嗎?我建議你使用單形函數,例如使用'Double',並且只在需要時才推廣。 –

+0

@ ThomasM.DuBuisson我實際上是在想爲樂趣:是否有任何_reasonable_類型既是'Floating'又是'Integral'?另外,有沒有一種方法可以根據實例來搜索類型,我們可以使用hoogle或hayoo來搜索基於類型的函數? – Alec

回答

5

這與數字文字在Haskell中重載的事實有關。當您輸入map(\x -> (x, div 18 x)) [y | y <- [1..(ceiling $ sqrt 18)], 18 `rem` y == 0]ghci時,作爲sqrt的參數的18默認爲Double,其他爲Integer s。

但是,當你寫

factorPairs:: (RealFrac a, Floating a, Integral a) => a -> [(a, a)] 
factorPairs n = map(\x -> (x, div n x)) [y | y <- [1..(ceiling $ sqrt n)], n `rem` y == 0] 

你逼的n所有實例都只有一個類型。然後,問題就變成了:沒有默認的數字類型(實際上我認爲是數字類型)可以滿足所有這些約束條件,因此GHC會告訴您它嘗試的「可能的實例」。該解決方案是增加fromIntegral和放寬這些限制:

factorPairs:: Integral a => a -> [(a, a)] 
factorPairs n = map(\x -> (x, div n x)) [y | y <- [1..(ceiling $ sqrt $ fromIntegral n)], n `rem` y == 0] 
4

另一種方式來擺脫錯誤類型是消除使用sqrt。由於Haskell是懶惰的,你可以簡單地遍歷[1..n],當你的除數大於你的商時停止。

factorPairs :: Integral a => a -> [(a, a)] 
factorPairs n = takeWhile (uncurry (>=)) [ (n `div` d, d) | d <- [1..n], n `mod` d == 0] 

uncurry (>=)是寫\(q, d) -> q >= d的只是一種奇特的方式。

如果你以單子形式寫這個,你可以使用divMod來獲得單個函數全部的商和餘數。

factorPairs n = takeWhile (uncurry (>=)) $ do 
       d <- [1..n] 
       let (q, r) = n `divMod` d 
       guard $ r == 0 
       return (q, d)