2012-02-28 63 views
5

下面的程序類型檢查我的命令行(如ghci file.hs)上指定它:ghci - 渴望在交互模式下編譯?如果

import Data.Ratio 
foo = let x = [1..] 
      y = (1%2) + (head x) 
     in y 

但是,如果我交互輸入它,我會得到一個錯誤類型:

Prelude> import Data.Ratio 
Prelude Data.Ratio> let x = [1..] 
Prelude Data.Ratio> let y = (1%2) + (head x) 
<interactive>:1:23: 
    Couldn't match expected type `Ratio a0' with actual type `Integer' 

它似乎x正在熱切地輸入爲[Integer],而不是更一般的(Num t, Enum t) => [t]

我能做些什麼嗎?是否有其他情況下交互模式與批處理模式不同?

+1

單態的限制... – augustss 2012-02-28 22:32:17

+1

並鍵入違約 – Ptival 2012-02-28 22:43:49

+3

事實上,這是可怕的單態的限制。有兩種方法:給出明確的簽名或關閉這個限制(在GHCi中,你可以執行':set -XNoMonomorphismRestriction'並完成了;語言編譯指示和編譯器標誌也起作用)。 – Vitus 2012-02-28 22:52:07

回答

10

綁定不帶任何參數,即那些形式x = ...的受monomorphism restriction,這意味着GHC將嘗試使用任何可用的類型信息使其變爲非多態,並且回退到type defaulting以解決任何amb iguities。 (其實,GHCi使用a slightly more permissive set of defaulting rules,但這對這個問題並不重要)。

由於在編寫let x = [1..]時沒有其他類型的信息可用,因爲Integer是默認的數字類型,所以鍵入默認值將導致類型被推斷爲[Integer]

有幾種方法來解決這個問題:

  1. 使用類型簽名。這總是有效,但在處理複雜類型時有時會很乏味。

    > let x = [1..] :: [Rational] 
    
  2. 用參數寫入綁定。這不適用於您的情況,但您在編寫無點函數定義時有時會看到此問題。

    > let f = (+) 
    > :t f 
    f :: Integer -> Integer -> Integer 
    > let f x y = x + y 
    > :t f 
    f :: Num a => a -> a -> a 
    
  3. 給類型檢查器更多信息。在你的情況下,我們可以通過在一個let聲明中寫入兩個綁定來避免該問題。 GHC然後可以使用來自第二次結合的類型信息來正確推斷x應該具有[Rational]的類型。

    > let x = [1..]; y = 1%2 + head x 
    > :t x 
    x :: [Ratio Integer] 
    
  4. 禁用單態限制。如果您預期某種東西的類型是例如一個Integer,而它實際上是一個Num a => a,因爲後者必須每次重新計算,而前者可以共享。這是限制首先存在的主要原因。

    但是,在解釋器中,這通常不是一個問題,所以方便通常是值得的。

    > :set -XNoMonomorphismRestriction 
    > let x = [1..] 
    > :t x 
    x :: (Num t, Enum t) => [t] 
    

    如果您希望在默認情況下啓用此功能,您可以將其添加到.ghci file

4

可以做點什麼通過定義x是以下幾點:

let x = [1..] :: [Ratio Int] 

爲:

Data.Ratio Prelude> let x = [1..] :: [Ratio Int] 
Data.Ratio Prelude> let y = (1%2) + (head x) 
Data.Ratio Prelude> y 
3 % 2 
Data.Ratio Prelude> 
+1

我強烈建議不要使用'Ratio Int',除非你絕對肯定地知道你的計算不會溢出,並且你對性能絕望 - 即使這樣我也不喜歡它。在我看來,使'Ratio'成爲一個多態類型是一個很糟糕的錯誤,即使很小的計算也可以輕易地超過64位,然後你會得到完全的廢話。 – 2012-02-29 05:11:12

相關問題