2012-10-02 63 views
7

我試圖編寫一個函數,它需要一個整數和一個三元組,並返回給定位置的三元組元素(練習5.3從Hickey的書中)。 Triplet應該能夠包含不同類型的元素。我認爲,如果我編寫3個小函數,每個函數都返回三元組中的特定元素,並使我的大函數相應地返回其中的一個,那麼它會執行這個技巧,但它不起作用。OCaml元組中的意外類型不匹配

我試圖擺弄這個「eta擴展」的概念,但我沒有得到它。

let nth1 (a, _, _) = a 
let nth2 (_, b, _) = b 
let nth3 (_, _, c) = c 

let nth i = match i with 
    | 1 -> nth1 
    | 2 -> nth2 
    | _ -> nth3 

let main = printf "%d\n" (nth 1 ("hello", 2, 'c')) 

所以它應該在這裏寫「2」。有什麼建議?

+1

編輯,因爲這不是真正的價值限制,稱它這樣會迷惑讀者。 –

回答

6

在編寫代碼之前,通常會考慮類型。什麼是你的功能的建議類型?

+0

嗯,我得到了像「int - >((a * b * c) - >(a或b或c))」,這顯然是錯誤的......感謝您揭露錯誤! – user1714986

+0

我認爲這是練習的要點。也許有點偷偷摸摸,但很好。 –

7

基本回答你的問題:

在OCaml中,該型系統的工作原理,將迫使nth只返回類型的方式。你想要的是類似交叉類型,但OCaml的靜態類型語義將改爲強制nth僅返回單個類型。其結果是你的元組必須退化爲元素是相同類型的情況。

讓我們考慮這種互動:

# let nth1 (a,_,_) =a;; 
val nth1 : 'a * 'b * 'c -> 'a = <fun> 
# let nth2 (_,b,_) = b;; 
val nth2 : 'a * 'b * 'c -> 'b = <fun> 
# let nth3 (_,_,c) = c;; 
val nth3 : 'a * 'b * 'c -> 'c = <fun> 
# let nth i = match i with 
     | 1 -> nth1 
     | 2 -> nth2 
     | _ -> nth3;; 
val nth : int -> 'a * 'a * 'a -> 'a = <fun> 

所以你的問題很奇怪,不是printf通話,因爲,而是因爲nth定義。相反,你可能會考慮製作一個獨特的類型,這是這幾種類型的組合。

事實上,您描述的行爲類型有點像依賴類型,其中實際得到的類型取決於的輸入值i。這當然應該是有問題的,因爲依賴類型比在ML中看到的允許多態性更具表達力!

我會說,你可以實例元組的做到這一點,例如,你可以做一個類型:

type IntOrStringOrX = int | string | X 

,然後你可以相應地寫下第n型的...

+0

謝謝你的幫助。我肯定會在以後看到類型和實例......這個問題在有關它們的實際章節之前就已經出現了。 – user1714986

+0

@ user1714986:有趣的..你能指點我一下書中的相關例子,它的做法是正確地做到這一點需要使用ocaml沒有的精心打字的系統。 –

+0

是的,這本書被稱爲J.Hickey介紹的Objective Caml(在線鏈接http://courses.cms.caltech.edu/cs134/cs134b/book。pdf)練習5.3。理論部分是第5章的前兩段。 – user1714986