2012-09-11 209 views
0

在Haskell中,我有一些定義函數的問題,因爲我的參數類型與所需的類型不匹配。爲什麼我收到類型錯誤?

例如,我想寫一個函數,該函數需要n :: Int並生成n的平方根的從1到floor的整數列表。因此,我將有一個功能,例如:

list :: Int -> [Int] 

本來我所定義的函數,如下所示:

list :: Int -> [Int] 

list n = [1 .. floor (sqrt n)] 

當我加載sript,存在不匹配的類型的錯誤消息。但是,我不確定我是否與sqrt函數或floor函數的類型不匹配。錯誤消息如下:

No instance for (Floating Int) 
    arising from a use of 'sqrt' at pe142.hs:6:22-27 
Possible fix: add an instance declaration for (Floating Int) 
In the first argument of 'floor', namely '(sqrt n)' 
In the expression: floor (sqrt n) 
In the expression: [1 .. floor (sqrt n)] 
Failed, modules loaded: none. 

有人可以向我解釋是什麼導致錯誤以及如何修復?

回答

6

sqrt需要Floating類的參數,例如,一個Double。你傳遞給它一個Int,這不是Floating類的一個實例 - 這就是錯誤信息告訴你的。

因此要修復錯誤,請在致電sqrt之前將您的Int轉換爲Double。您可以使用fromIntegral函數。

4

當我試試這個:

list :: Int -> [Int] 
list n = [1 .. floor (sqrt n)] 

我得到這個錯誤:

../src/scratch.hs:15:16: 
    No instance for (RealFrac Int) 
     arising from a use of `floor' 
    Possible fix: add an instance declaration for (RealFrac Int) 
    In the expression: floor (sqrt n) 
    In the expression: [1 .. floor (sqrt n)] 
    In an equation for `list': list n = [1 .. floor (sqrt n)] 

../src/scratch.hs:15:23: 
    No instance for (Floating Int) 
     arising from a use of `sqrt' 
    Possible fix: add an instance declaration for (Floating Int) 
    In the first argument of `floor', namely `(sqrt n)' 
    In the expression: floor (sqrt n) 
    In the expression: [1 .. floor (sqrt n)] 

什麼這些錯誤的意思是:

  • floor功能無法接受類型爲Int的論點。它的論點必須是「真實分數」類型。 (請求底層數字的類型只支持整數是沒有意義的。)
  • sqrt函數也不能接受類型爲Int的參數。它的參數必須是浮點類型。 (平方根通常是不合理的,所以我們需要一個浮點型。)

你會發現,Haskell是非常,有什麼方法可以應用於數字功能非常挑剔的,其數值類型,什麼類型非常挑剔這些函數返回,它基本上不執行隱式轉換。我通常會嘗試讓編譯器推斷數字代碼中的類型,因爲類層次結構非常複雜。如果我們離開了你的函數的類型聲明,編譯器推斷該類型:

list :: (Floating a, Integral t, RealFrac a) => a -> [t] 

也就是說,你list功能函數需要一個浮點「真實分數」作爲其參數,併產生整數作爲列表其結果。因此,例如,list可以採用類型爲Double的參數並生成[Integer]

即使遺漏類型聲明並不意味着你不會遇到麻煩,而且你經常不得不使用顯式類型轉換;最典型的是您必須使用函數fromIntegral將整數類型轉換爲小數類型。

1

SQRT具有以下類型簽名:

Floating a => a -> a 

這意味着,SQRT採用類型A的參數,並返回類型的參數。重新定義是a必須是類型Floating的類型,通常是Single或Double。 int是不是在類型類浮動,所以你需要到n轉換的東西,是在類型類浮動,您可以通過添加一個調用fromIntegral做到這一點:

list n = [1 .. floor (sqrt (fromIntegral n))] 
0

這個問題被問一次周。 (這不是對你的投訴,只是一個觀察,顯然這讓很多人感到困惑。)

簡而言之,sqrt不適用於整數,只適用於浮點數。 (例如,它不適用於Int,但它的確適用於Double。)在某些編程語言中,在這種情況下,整數總是自動「升級」爲浮點數;但在Haskell中,您必須手動執行此操作。

這個解決方案,其他六個人毫無疑問已經寫好了,其中的一個解決方案是將fromIntegral添加到那裏,以便將整數轉換爲浮點數。您已經擁有floor,您可以按照預期將其轉換回整數。

相關問題