2010-07-25 35 views
1
class Visible a where 
toString :: a -> String 
size :: a -> Int 

intToString :: (Integral t) => t -> String 
intToString 0 = "0" 
intToString 1 = "1" 
intToString 2 = "2" 
intToString 3 = "3" 
intToString 4 = "4" 
intToString 5 = "5" 
intToString 6 = "6" 
intToString 7 = "7" 
intToString 8 = "8" 
intToString 9 = "9" 
intToString n 
| ((div n 10) == 0) = (intToString (mod n 10)) 
| otherwise   = (intToString (div n 10)) ++ (intToString (mod n 10)) 

現在詮釋VS整數類實例

instance Visible Int where 
toString = intToString 
size n = length (toString n) 

給我約一個模糊的類型變量的錯誤在提示符下,如果我輸入類似(的toString 55)

instance Visible Integer where 
toString = intToString 
size n = length (toString n) 

沒有。

什麼給?

+3

僅供參考,這裏是你的intToString的另一種定義:'intToString = show' – luqui 2010-07-25 16:05:19

回答

0

我找到this link一個可能的解釋。我認爲文字的默認解釋是ghci中的整數。但如果這樣做不成立,ghci開始對他必須做出的字面解釋(Int,Double,Float,...)感到困惑。 隨後,他給出了有關歧義的錯誤。命令(toString (55:Int))不會產生錯誤,因爲GHCi知道他必須將55解釋爲Int

應用此方法不是爲特定類型的值,但另一個重載型,以 值即你的文字5.這 意味着Haskell有找出哪些具體的類型來選擇 爲在這種情況下「a」。 Haskell的類型類是開放的,並且它通常不隨機 選擇一個,如果多個可能匹配。在這種情況下,Integer(在你的第一個例子中)或Int(在你的第二個例子中)有一個實例 ,但 也可能是Float或Double的另一個例子。哪一個會是 是正確的?那麼,正如我所說的,通常哈斯克爾在這裏保守,並且只是抱怨,因此在第二種情況下得到了「不明確類型變量」錯誤 。 但是,Haskell中有一種機制可以給出啓發式規則,而 這就是「違約」的全部內容。在正常情況下,對於數字類型, 對於不明確的情況,在數字類型中選擇「Integer」,如果不起作用,它將嘗試「Double」。它不嘗試「詮釋」 雖然。這解釋了爲什麼你的第一個例子(偶然)起作用。 如果你問GHCi的類型,默認不適用,但你可以觀察到它發生在很多地方。例如,

15

這裏有兩件事情。請記住,Haskell中的數字文字是多態的。那就是:

x = 55 

的真正含義

x :: Num a => a 
x = fromIntegral 55 

這是任何你寫他們所有的數字屬實。這可能很難處理,所以GHCi實現了類型默認:如果類型不明確,它假定裸號是IntegersDoubles

當您在GHCi提示處編寫toString 55時,GHCi推斷數字55爲(Visible a, Num a) => a。如果您只有Visible Int的範圍,則缺省類型Integer不起作用,因爲它沒有滿足類約束(沒有Visible Integer),所以GHCi抱怨模糊類型變量,因爲它不知道要實例化哪種類型爲表達。如果你在範圍內有Visible Integer,Integer默認的類型工作得很好。

如果你想使用整數以外的類型,你可以用一個明確的類型,如toString (55 :: Int)