(更新:顯然,我原來的答覆是不能爲OP非常有幫助...查看第二HR下面的附錄)。
在這樣的情況下,你真正想要的要做的是啓動ghci
並使用:t
來找出各種表達式的類型。例如。
:t foldr map
-- answer: foldr map :: [b] -> [b -> b] -> [b]
如果你需要首先定義一個名字,使用let
(這不是一個Haskell源文件需要):
let mys = undefined :: a -> a
:t map mys
-- answer: [a] -> [a]
注意使用undefined
有一個明確的類型簽名。找出各種形式的表達式類型是完全可以的,甚至可以在實際的代碼中作爲佔位符在早期計劃階段有用。
Num a =>
是a
上的類型約束;見例如從「真正的世界Haskell」的「A Gentle Introduction to Haskell,Version 98」或獲得更多信息。 (基本上,它做什麼,你認爲它。:-))
以上應該是驗證你的答案非常有用(和類型類的資源都不錯)。至於如何自己解決這類問題:
類型推斷是所謂的「統一算法」的應用。谷歌爲一些資源「統一」;如果您爲查詢添加編程語言的名稱,則可能會找到示例實現。
至於如何處理手頭的例子......
a。 map mys
:map
採用類型爲a -> b
的函數並返回類型爲[a] -> [b]
的函數。通常,a
可以不同於b
,但mys
的類型爲a -> a
,因此返回的函數將是[a] -> [a]
類型。
下面是一些手工統一:
(a -> b) -> [a] -> [b]`
(a -> a)`
^-- at this point we unify a with b;
when propagated to the return type,
this produces [a] -> [a]
灣mys map
:mys
是一個函數,它接受某種類型的對象並返回相同類型的對象。特別是,如果你傳遞一個類型爲(a -> b) -> [a] -> [b]
的參數,那將是返回值的類型。
順便說一下,只有一個「有趣的」(不是undefined
)函數的類型簽名是a -> a
(沒有類型約束),即id
。請參閱Philip Wadler的論文「免費定理!」 (您可以從this page下載)進行擴展討論。
c。首先,請注意foldr
的a
s和b
s的簽名與map
的簽名沒有任何關係。重命名map
的a
至c
和b
至d
並使用簽名map :: (c -> d) -> [c] -> [d]
以使其更容易在下面顯而易見。還請注意,(a -> b -> b)
只是一種簡單的寫作方式(a -> (b -> b))
。
更多手工統一(以下解釋如下):
(a -> (b -> b))
(c -> d) -> [c] -> [d]
這裏會發生什麼事是,foldr
需要(a -> (b -> b))
類型的函數參數。如果您在map
作爲參數傳遞時,a
獲取與c -> d
統一的b
與[c]
,然後再次[d]
,這意味着c
等於d
。
foldr
的返回值爲b -> [a] -> b
;代入前面的段落中獲得的更具體的類型,我們得到
[c] -> [c -> c] -> [c]
^-- c equals d, right?
的c
來自我們改變了簽名map
;與原來的b
,這變成
[b] -> [b -> b] -> [b]
d。 foldr map . mys
:這實際上是(foldr map) . mys
,而不是foldr (map . mys)
- 函數應用程序(「不可見的運算符」)綁定最強!合併一個。和c。從上面解決這個問題留給讀者做一個練習。 ;-)
謝謝,但我寫:t在我的考試紙上不會給我一個答案。呵呵。 那就是爲什麼我試圖去了解爲什麼它是[b] - > [b-> b] - > [b] – 2010-05-11 21:28:58
哦,我明白了。希望我最近編輯的答案會更有幫助。 – 2010-05-11 22:52:20
我得到[a] - > [a-> a] - > [a]爲'd'。 :t檢查是正確的,謝謝! – 2010-05-12 03:09:11