2014-10-20 81 views
3

任何人都可以解釋爲什麼haskell在下面的例子中強制顯式類型簽名,以及如何修改它以避免需要顯式聲明?模糊的類型變量,但不在ghci中?

import qualified Data.List as L 

main = do 
    print $ length $ L.nub [1,1,2,3] -- 3, passed (Eq a, Num a) => [a] 
    print $ length $ L.nub []   -- ambiguous type error, passed (Eq a) => [a] 
    -- can help type system with explicit signature but how to avoid ? 
    print $ length $ L.nub ([] :: [Int]) 

令人驚訝的在ghci的交互書寫的同一代碼有沒有問題,有不確定性和不打印零長度:

λ> :m +Data.List 
λ> print $ length $ nub [] 
0 -- ?? can you explain ?? 

更新: 看來即使相同的限制,Data.List.nub長度功能將不停止關於曖昧類型的投訴:

length' :: Eq a => [a] -> Int 
length' [] = 0 
length' (x:xs) = 1 + length' xs 

main = do 
    print $ length' $ nub [] 
-- No instance for (Eq a0) arising from a use of ‘length'’ 
-- The type variable ‘a0’ is ambiguous 
+0

默認情況下,ghci打開擴展默認規則('-XExtendedDefaultRules'),請參閱[這裏](https://www.haskell.org/ghc/docs/7.8.2/html/users_guide/interactive-evaluation。 html),請參閱第2.4.8節。 – 2014-10-20 13:58:29

+0

謝謝。這是一個隱藏的標誌,因爲ghci不會用':show language'列出它。我的基礎語言是:Haskell2010 使用以下修飾符: -XNoDatatypeContexts -XNondecreasingIndentation'? – 2014-10-20 14:35:41

+0

我認爲這些規則僅適用於交互式輸入而不適用於加載的模塊,因此真正的編譯器標誌並非「真正」開啓。 – 2014-10-20 19:05:39

回答

7

問題是[]具有多態性類型(Eq a) => [a]。由於length不會添加任何特定的限制。

具體的length類型是:

length :: [a] -> Int 

這甚至比nub更寬容:

nub :: Eq a => [a] -> [a] 

編譯器需要使用的length有一個特定的實例,並不能推斷出一種類型爲a

現在你有兩個選擇:

  1. 接通ExtendedDefaultRules擴展與{-# LANGUAGE ExtendedDefaultRules #-}在文件的開頭。
  2. 要明確:... L.nub ([] :: [Int])

我默認推薦:第二個,除非你完全瞭解consequences of the first one

+0

感謝您的回答。你還可以解釋爲什麼同樣特殊的長度函數像'length':: Eq a => [a] - > a'不會有幫助,我仍然會遇到模糊的類型錯誤? – 2014-10-20 14:33:26

+0

@DavidUnric因爲編譯器不能推導出'a',因爲有> 1個數據類型滿足'Eq' * equal * well(雙關語並非意圖)。我可以問你正在研究Haskell的書嗎? AFAIK大部分書籍都在上半年討論了這個話題。 – Shoe 2014-10-20 14:43:03

+0

確實有很多類'Eq'的實例,只是希望類型系統可以從'[] :: Eq t => [t]'推斷'足夠'長度',因爲通用類型足以計算列表的長度。 – 2014-10-20 14:55:40