2017-03-03 149 views
4

通過「從第一原理哈斯克爾編程」的工作,我的回答感到迷惑不解以下問題:哈斯克爾返回類型混亂

如果kessel類型爲(Ord a, Num b) => a -> b -> a,那麼 kessel 1 2類型是

一個)Integer
b)中Int
C)a
d)(Num a, Ord a) => a
E)Ord a => a
F)Num a => a

答案是d) - 但我認爲答案應該是E),因爲在類型簽名的第一個參數,唯一的要求(a)爲它是一個Ord。那麼,爲什麼不回報?

kessel 'd' 2 

是有效的,這是Char類型 - 一無所知Num

我不明白什麼?

謝謝你的幫助。

+4

我們要求'Num a'以便'1 :: a'有意義。 –

+4

作爲一個側面說明,這個問題真的很糟糕:「正確」的答案很大程度上取決於Haskell類型系統的一些不太有趣的變化,特別是默認和數字字面多態性,並取決於你如何解釋這個問題還有單態限制。如果你對'Num b'約束使用了一個不同於'Num'的類(當然還有一個適當的'2'的替代參數),那麼正確答案可能就是「這是一個模糊的類型錯誤」,如果你在文件中寫入'foo = kessel 1 2',並向ghci詢問它的類型,它會告訴你'foo :: Integer'! –

+1

......而且要明確,通過「這個問題」,我並不是說你要問的問題很糟糕。我認爲你在設置你的問題方面做得很好。我在說「來自第一校長的Haskell編程」這個問題令人困惑,並且(在我看來)是一個嚴重的問題。 –

回答

5

1的類型是Num a => a。當您將其作爲第一個參數傳遞給kessel時,其類型限制爲(Num a, Ord a) => a,因爲kessel需要Ord作爲其第一個參數。由於結果的類型與第一個參數的類型相同,因此您會得到(Num a, Ord a) => a作爲結果類型。

請注意,這與第二個參數的類型無關。我想第二個參數就是在那裏混淆你。如果函數爲:

kessel :: Ord a => a -> a 

那麼kessel 1類型仍然是(Num a, Ord a) => aNum在那裏,因爲這是1的類型,而不是因爲kessel的類型。

類型的kessel 'd' 2Char,相對於Ord Char => Char,因爲Char是已經實現Ord一個具體類型,因此限制是不必要的。

+0

」...那麼凱塞爾1的類型仍然是(數字a,奧德a)=> a。數字在那裏,因爲這是1的類型,不是因爲凱塞爾的類型。啊......揭開了面紗。謝謝你。 – ericky

1

kessel 'd' 2

是有效的,這是Char類型 - 一無所知Num

是的! kessel 1 2kessel 'd' 2有不同的類型,

λ> kessel = undefined :: (Ord a, Num b) => a -> b -> a 
kessel :: (Num b, Ord a) => a -> b -> a 

λ> :t kessel 1 2 
kessel 1 2 :: (Num a, Ord a) => a 

λ> :t kessel 'd' 2 
kessel 'd' 2 :: Char 

這是可能的,因爲kessel多態性