2015-10-09 85 views
3

我想定義一個函數check_char_fun:(char - >'a) - >(char - >'a) - > bool,如果char上有兩個函數 ,當兩個函數相同時返回true (即,當它們在char的每個可能值上完全相同的行爲時),否則爲false。OCaml檢查函數

let check_char_fun f1 f2 = 
let aux = true 
for i=0 to 255 do 
    if (f1 (char_of_int i))=(f2 (char_of_int i)) 
    then aux=false; 
done; 
if aux=true 
then true 
else false;; 

我在學習OCaml,所以我不知道該怎麼辦。

回答

2

你就要成功了:

let check_char_fun f1 f2 = 
    let aux = ref true in 
    for i = 0 to 255 do 
    if (f1 (char_of_int i)) = (f2 (char_of_int i)) then aux := false 
    else() 
    done; 
    !aux 

不像變量在命令式語言,在OCaml中的綁定默認情況下是不可變的。要創建一個實際變量,我們創建一個bool ref,它是可變的,可以在循環內進行更改。

OCaml在命令式語言等語句和表達式之間沒有區別:只有表達式!這就是爲什麼你總是需要else條款if;通過這種方式,得到的表達式總是返回一個值(在ifelse的情況下),其類型必須相同 - 在此例中爲unit(值爲() - 在C中爲void)。

你的代碼不像OCaml那樣,但那就是我個人對OCaml的喜愛:功能風格並不是強迫你的喉嚨,你可以在沒有進入學術象牙塔的情況下實現一種命令式的算法。

2

首先,你必須定義一個「行爲」是什麼。如果你的功能可能引發異常,問題會變得更加困難。你的代碼假設函數總是返回一個值,這對於一個開始的問題來說似乎是一個很好的簡化。

您也正在使用OCaml使用的字符(有點過時)的定義,因爲代碼被限制在0到255的範圍內。

因此,我在代碼中看到的唯一問題是您期望能夠更改aux變量的值。 OCaml中的變量是不可變的:你不能改變它們綁定的值。

如果您想保留大部分代碼,您可以將aux更改爲其值爲參考爲bool。然後,您可以更改內部的布爾值的參考(而aux仍然綁定到相同的參考)。

要對一個布爾參考,並更改值:

# let x = ref true;; 
val x : bool ref = {contents = true} 
# !x;; 
- : bool = true 
# x := false;; 
- : unit =() 
# !x;; 
- : bool = false 

(其中一個原因,研究OCaml的是學習如何與不變的價值觀工作,所以我建議尋找其他途徑以解決不需要使用引用的問題。)

1

以下內容將每個函數應用於0到255範圍內的每個字符值並比較它們的結果,但它不檢查函數引發異常或在別處引起副作用:

open Core.Std 
let check_char_fun f1 f2 = 
    let chars = List.map ~f:char_of_int (List.range 0 256) in 
    List.for_all ~f:(fun c -> (f1 c) = (f2 c)) chars 
+1

標準庫中沒有'List.range',也沒有'List.for_all'的標籤版本(在這種情況下使用帶標籤的參數似乎是不必要的分心)。 –

+0

它們在'Core.Std'中。 –

1
let rec range i j = 
    if i > j then [] else i :: (range (i+1) j);; 

let check_char_fun f1 f2 = 
    let lc = List.map char_of_int (range 0 255) in 
    List.for_all (fun c -> (f1 c) = (f2 c)) lc;; 

測試:

#let id x =x;; 
val id : 'a -> 'a = <fun> 
# check_char_fun id id;; 
- : bool = true 
# check_char_fun id (fun x -> 'a');; 
- : bool = false 

或者:

exception Fails_in of char;; 
let check_char_fun f1 f2 = 
    let lc = List.map char_of_int (range 0 255) in 
    List.iter (fun c -> 
    if (f1 c) <> (f2 c) then raise (Fails_in c) 
) lc;; 

# try (
    check_char_fun id id 
) with Fails_in c -> Printf.printf "Diff(%d)(%c)" (int_of_char c) c 
;; 
    - : unit =() 


# try (
    check_char_fun id (fun x -> 'a') 
) with Fails_in c -> Printf.printf "Diff(%d)(%c)" (int_of_char c) c 
;;  
Diff(0)()- : unit =() 
+0

現在我創建了: 異常Fails_in of char; 我想定義相同的函數Check_char_fun,但我認爲它必須是(char - >'a) - >(char - >'a) - >單位如果我想拋出異常。 所以check_char_fun f1 f2 return()如果f1和f2是相同的函數,或者Fails_in c如果c是char其中f1 c和f2 c不是相同的函數。 我不能用List.map來做,我可以嗎? –

+0

@ChenYo:爲了在發生不匹配時發生異常,將傳遞給'List.for_all'的函數的主體改爲'(f1 c)=(f2 c)||提高(Fails_in c)'。 –