OCaml 检查函数

OCaml checking functions

我想定义一个函数 check_char_fun: (char -> 'a) -> (char ->' a) -> bool that, 给定两个函数 在 char 上,return 当两个函数相同时为 true(即,当它们在 char 的每个可能值上的行为完全相同时)否则为 false。

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,所以我不知道我能做什么。

首先,您必须定义 "behavior" 是什么。如果您的函数可以引发异常,问题就会变得更难。您的代码假定函数总是 return 一个值,这似乎是对开始问题的一个很好的简化。

您还使用了 OCaml 使用的(有点过时的)字符定义,因为代码被限制在 0 .. 255 范围内。这似乎也可以。

所以我在您的代码中看到的唯一问题是您希望能够更改 aux 变量的值。 OCaml 中的变量是不可变的:您不能更改它们绑定的值。

如果您希望大部分代码保持原样,您可以更改 aux,使其值为 reference 布尔值。然后您可以更改 inside 引用的布尔值(而 aux 仍然绑定到相同的引用)。

要引用 bool 并更改值:

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

(学习 OCaml 的原因之一是学习如何使用不可变值。所以我建议寻找其他不需要使用引用的方法来解决问题。)

以下将每个函数应用于 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
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 = ()

你快到了:

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

与命令式语言中的 variables 不同,OCaml 中的 bindings 默认是不可变的。要创建一个 真正的变量 ,我们创建一个 bool ref,它是可变的并且可以在循环中更改。

OCaml 不像命令式语言那样区分语句和表达式:只有表达式!这就是为什么你总是需要 else 子句到 if;这样,结果表达式总是 returns 一个值(在 ifelse 的情况下)其类型必须相同 - 在这种情况下类型 unit (值的类型 () —— 在 C 中为 void)。

你的代码不是很像 OCaml,但这就是我个人喜欢 OCaml 的地方:函数式风格不会被你逼到喉咙里,你可以在不进入学术象牙塔的情况下以命令式风格实现算法。