OCaml检查功能

时间:2015-10-09 16:30:46

标签: ocaml

我想定义一个函数check_char_fun:(char - >'a) - > (char - >'a) - > bool,给出了两个功能 在char上,当两个函数相同时返回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,所以我不知道该怎么做。

4 个答案:

答案 0 :(得分:2)

首先,您必须定义“行为”是什么。如果您的函数可以引发异常,则问题会变得更加困难。您的代码假设函数始终返回一个值,这似乎是对开始问题的一个很好的简化。

你也在使用OCaml使用的(稍微过时的)字符定义,因为代码限制在0 .. 255范围内。这也似乎没问题。

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

如果您希望保持代码大部分不变,可以更改aux,使其值为引用到bool。然后你可以改变 in 引用的布尔值(aux仍然绑定到同一个引用)。

要引用bool并更改值:

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

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

答案 1 :(得分: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中的 bindings 默认情况下是不可变的。要创建实变量,我们创建一个可变的bool ref,可以在循环中进行更改。

OCaml在命令式语言之类的语句和表达式之间没有区别:只有表达式!这就是为什么你总是需要else条款到if;这种方式生成的表达式总是返回一个值(在ifelse情况下),其类型必须相同 - 在这种情况下类型为unit(类型为值() - 在C中为void

你的代码不像OCaml那样,但这就是我个人对OCaml的喜爱:功能风格并没有被强行扼杀,你可以在不进入学术象牙塔的情况下以强制性的方式实现算法。

答案 2 :(得分: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

答案 3 :(得分: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 = ()