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 一个值(在 if
和 else
的情况下)其类型必须相同 - 在这种情况下类型 unit
(值的类型 ()
—— 在 C 中为 void
)。
你的代码不是很像 OCaml,但这就是我个人喜欢 OCaml 的地方:函数式风格不会被你逼到喉咙里,你可以在不进入学术象牙塔的情况下以命令式风格实现算法。
我想定义一个函数 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 一个值(在 if
和 else
的情况下)其类型必须相同 - 在这种情况下类型 unit
(值的类型 ()
—— 在 C 中为 void
)。
你的代码不是很像 OCaml,但这就是我个人喜欢 OCaml 的地方:函数式风格不会被你逼到喉咙里,你可以在不进入学术象牙塔的情况下以命令式风格实现算法。