2017-04-01 61 views
1

每當我運行代碼時,disting truedisting false也變成了expression1。結果反之亦然此代碼與int和bool匹配的ocaml模式

let disting v = 
    match v with 
    | bool -> (*expression2*) 
    | int -> (*expression1*)  
    | _ -> (*expression3*) 

這也有類似的問題。我怎樣才能得到我想要的結果?

回答

4

模式匹配不像您認爲的那樣工作。

它可以讓你匹配值或像在以下值的方式表達:

match some_int with 
| 1 -> 1 
| 10 -> 2 
| x -> x/2 (* this matches any possible int, and it gives it the name 'x' for the rest *) 

所以在這裏你的意志,因爲它沒有任何的濾液的第一種情況總是匹配。你所說的是:用任何東西與v相匹配,在其餘部分我們稱它爲'bool'。

你便可以嘗試像

let disting v = 
    match v with 
    | true -> (*expression2*) 
    | 2 -> (*expression1*)  
    | _ -> (*expression3*) 

不OCaml中進行類型檢查爲「V」或者是一個int或一個布爾值,但不能同時。 我不知道你想做什麼,但你應該讀一些關於語言的基礎。

1

做OCaml中的方法是使用和類型:

 type i_or_b = I of int | B of bool; 
     let disting v = 
     match v with 
     | I x -> Printf.printf "v = I %d\n" x 
     | B x -> Printf.printf "v = B %s\n" (string_of_bool x) 
0

TL;博士:寫兩個不同的功能,一個int和一個布爾值,並調用相應的一個根據上下文。

Pierre G.給出了一個很好的方法來實現你想要做的事情。儘管如此,我想補充一點,我相信你在函數編程中試圖完成的是根本錯誤;在運行類型中檢查類型是典型的命令式編程。這是爲什麼:

函數是一個地圖,需要從空間中的一些元素,並從另一個空間輸出的元素,這就是爲什麼在數學上,我們寫f: X -> Y表示,一個功能是從太空X的地圖空間Y。特別是它的含義是f只能將X中的元素作爲輸入。如果X是自然數的空格,那麼調用f(dog)是沒有意義的。

我們所說的一切基本上都是在函數式編程中發生的,只是用類型替換空間,並且你得到一個函數是從一個類型到另一個類型的映射。這就是爲什麼我們使用諸如f :: int -> int這樣的符號作爲我們的函數簽名,那麼它將不會很好地定義什麼f true意味着什麼,因此您的程序將無法編譯,因爲它沒有任何意義。

因此,您可以再次使用Pierre的解決方案並定義一個實際上是int和bool聯合的類型(空間)。

type intOrBool = Int of int | Bool of bool;

然後定義intOrBool -> [output type]類型的函數。但是再次理解它不同於可以接收int或者bool的函數,因爲intOrBool是一種全新的類型。

爲什麼以這種方式考慮問題非常重要?因爲函數式編程的強度正是這樣的:如果它沒有明確定義,它就不會編譯。在命令式語言中,你有一些函數可以接收某些類型,比如int,但是仍然可以接受任何東西。這可以使他們崩潰,或最糟糕的給予意想不到的行爲,可能導致混亂,咖啡濫用和security breaches。從更實際的角度來看,這實際上是我們剛纔解釋的理論的結果,OCaml在運行時不會跟蹤類型。類型檢查都是在編譯之前完成的,因爲一旦我們知道每件事都會被明確定義,那麼爲什麼我們會留意這些信息呢?在數學上,我們確信,錯誤類型不會發生錯誤。

總之,我個人對你的問題的回答是,你應該寫兩個不同的函數,一個取int和一個取bool並實現你想要的行爲。這具有可重用性的優點,對於大多數情況下想要完成的任務來說都是有益的,並且最終更接近於通常在函數編程中使用的策略,這種編程是編寫並編寫小型構建塊功能。