2012-03-30 29 views
5

以下等式是用Miranda語法編寫的,但由於Miranda和Haskell之間的相似性,我期望Haskell程序員應該理解它!確定函數式編程中函數的類型

如果定義了以下功能:

rc v g i = g (v:i) 
rn x = x 
rh g = hd (g []) 


f [] y = y 
f (x:xs) y = f xs (rc x y) 

g [] y = y 
g (x:xs) y = g xs (x:y) 

你如何制定出的功能類型?我想我明白如何解決f,g和rn問題,但我對部分應用程序部分感到困惑。

RN將是* - > *或任何東西 - >什麼,我認爲這是一個 - 在Haskell>一個

對於f和g,是函數類型都[*] - > * - > *

我不確定如何處理尋找rc和rh的類型。在rc中,g被部分應用於變量i - 所以我猜測這限制了我的類型[*]。 rc和g在rc的定義中應用了什麼順序? g是否應用於i,然後將得到的函數用作rc的參數?還是rc需要3個獨立的v,g和i參數?我真的很困惑..任何幫助將不勝感激!多謝你們。

對不起忘了補充一點,HD是列表的標準頭功能,並定義爲:

hd :: [*] -> * 
hd (a:x) = a 
hd [] = error "hd []" 
+0

這是功課嗎? – 2012-03-30 13:07:53

+0

不,我現在正在準備考試,這是一個米蘭達考試的老考試問題。 – user1058210 2012-03-30 13:11:42

+0

「hd」功能的類型是什麼? – 2012-03-30 13:12:57

回答

6

類型是從什麼是已知的類型和表現形式是如何在定義中使用的推斷。

讓我們開始在頂部,

rc v g i = g (v : i) 

所以rc :: a -> b -> c -> d,我們必須看看有什麼可以發現關於a, b, cd。在右側,出現(v : i),因此使用v :: a時,我們看到i :: [a],c = [a]。然後g應用於v : i,所以g :: [a] -> d,乾脆,

rc :: a -> ([a] -> d) -> [a] -> d 

rn x = x意味着有上參數類型的rn沒有約束,它的返回類型是一樣的,rn :: a -> a

rh g = hd (g []) 

由於rh的說法g被施加到在RHS空列表,它必須有類型[a] -> b,可能更多的信息有關ab如下。事實上,g []hd在RHS,所以g [] :: [c]g :: [a] -> [c]的說法,因此

rh :: ([a] -> [c]) -> c 

下一頁

f [] y = y 
f (x:xs) y = f xs (rc x y) 

第一個參數是一個列表,如果是空的,結果是第二個參數,所以f :: [a] -> b -> b從第一個方程得出。現在,在第二個方程中,在RHS上,f的第二個參數是rc x y,因此rc x y必須與y具有相同的類型,我們將其稱爲b。但是

rc :: a -> ([a] -> d) -> [a] -> d 

,所以b = [a] -> d。因此

f :: [a] -> ([a] -> d) -> [a] -> d 

最後

g [] y = y 
g (x:xs) y = g xs (x:y) 

從第一個方程推導出g :: [a] -> b -> b。從第二個,我們推斷b = [a],因爲我們採取g的第一個參數和缺點它的第二個頭部,從而

g :: [a] -> [a] -> [a] 
+0

謝謝丹尼爾!用第一個方程rc,我們將g應用於我們已經確定爲類型[a]的i - 但是我們如何知道函數的輸出是類型d?這不僅僅是rc的輸出,也不一定是g的輸出? – user1058210 2012-03-30 14:29:55

+0

我們對'rc'定義的'g'結果類型一無所知,所以無論傳入參數'g'的結果類型是該調用中'rc'的結果類型。對於可以是任何類型的類型,我們使用類型變量,無論我們稱之爲「d」還是「simon」都不重要。在這裏,我們不能稱之爲'a',因爲這已經被用於另一種類型(但是傳遞'g1 :: [b] - > b'是合法的,'d'類型可能等於'a' ,但它不需要,因此得到不同的外延)。我留下了'd',因爲這就是'rc'類型的第一個近似值的結果類型。 – 2012-03-30 14:36:22

+0

如果rc的結果只是另一個g函數,爲什麼rc的輸出沒有給出[a] - > d?整件事: rc :: a - >([a] - > d) - > [a] - >([a] - > d) – user1058210 2012-03-30 14:58:07

6

我要使用Haskell語法來寫的類型。

rc v g i = g (v:i) 

這裏rc有三個參數,所以它的類型將會像a -> b -> c -> dv:i必須是與vi相同類型的元素列表,因此v :: ai :: [a]g應用於該列表,以便g :: [a] -> d。 如果你把所有的東西放在一起,你會得到rc :: a -> ([a] -> d) -> [a] -> d

正如你已經想出rn :: a -> a,因爲它只是身份。

我不知道您在rh中使用的hd函數的類型,所以我會跳過它。

f [] y = y 
f (x:xs) y = f xs (rc x y) 

這裏f有兩個參數,所以它的類型將會像a -> b -> c。 從第一種情況我們可以推斷出b == c,因爲我們返回y,並且第一個參數是一個列表。 現在我們知道f :: [a'] -> b -> b。 在第二種情況下通知如何xy在輸入給予rcy必須是一個函數[a'] -> d,和rc x y :: a' -> d(即必須也y的類型,因爲它是作爲它的f秒參數傳遞)。 最後,我們可以說f :: [a'] -> ([a'] -> d) -> ([a'] -> d)。由於->是正確關聯的,因此相當於[a'] -> ([a'] -> d) -> [a'] -> d

你可以用同樣的方式推理其餘的。

+0

'hd'來自Miranda標準庫。它相當於Haskell中的'head',所以它的類型是'[a] - > a''。 – hammar 2012-03-30 14:15:51

+0

謝謝Riccardo!你能否看看我問過丹尼爾的問題,因爲它也適用於你的答案 - 謝謝! – user1058210 2012-03-30 14:31:52

+0

高興。對不起,我遲到了。他已經解釋過你:) – 2012-03-30 15:13:45