Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
OCaml中的操作替换_Ocaml - Fatal编程技术网

OCaml中的操作替换

OCaml中的操作替换,ocaml,Ocaml,我手头有一项任务,我已经完成了90%,只是不知道如何完成它。因此,任务如下:“编写一个非递归函数,它接受一个函数和两个列表作为输入,并返回第三个列表,其中包含应用于两个输入列表中所有可能的元素对的函数结果。”因此,我必须按如下所示获取它 # cart_fun ( * ) [1;2;2;6;3;9;1] [2;3];; -: int list = [2; 3; 4; 6; 4; 6; 12; 18; 6; 9; 18; 27; 2; 3] 我的困难在于我不知道如何进行函数替换。这是我的密码 le

我手头有一项任务,我已经完成了90%,只是不知道如何完成它。因此,任务如下:“编写一个非递归函数,它接受一个函数和两个列表作为输入,并返回第三个列表,其中包含应用于两个输入列表中所有可能的元素对的函数结果。”因此,我必须按如下所示获取它

# cart_fun ( * ) [1;2;2;6;3;9;1] [2;3];; -: int list = [2; 3; 4; 6; 4; 6; 12; 18; 6; 9; 18; 27; 2; 3]
我的困难在于我不知道如何进行函数替换。这是我的密码

let cart_fun list1 list2 =
  let res = List.fold_left (fun acc x -> List.fold_left (fun acc y -> (x * y) :: acc) acc list2) [] list1
  in List.rev res;;
但我希望在部分(x*y)中,乘法作为列表前的参数给出


提前感谢您的帮助。

大部分旅程已经完成!做得好! 通过使用
fold_left
函数可以看到,在OCaml中(与其他函数语言一样),可以将函数作为参数传递(甚至返回),这就是为什么可以为
fold_left
提供累加函数的原因。这是您的代码:

让购物车乐趣列表1列表2=
让res=List.fold_向左(趣味acc x->
List.fold_left(趣味acc y->(x*y)::acc)acc list2)
[]清单1
在List.rev res;;
即使代码非常好,让我们重新表述一下,以便更清楚地看到它

let cart_fun list1 list2=
让进程列表2 fst acc=
List.fold_左
(有趣的snd_acc y->(x*y)::snd_acc)
fst_acc
清单2
在里面
让结果=List.fold_left(有趣的附件x->process_List_2附件x)[]列表1在
List.rev结果
正如您可能已经意识到的:
(fun acc x->process\u list\u 2 acc x)
实际上与
process\u list\u 2
相同,因此,让我们再重复一次:

let cart_fun list1 list2=
让进程列表2 fst acc=
List.fold_左
(有趣的snd_acc y->(x*y)::snd_acc)
fst_acc
清单2
在里面
让result=List.fold\u left process\u List\u 2[]list1 in
List.rev结果
但是,嘿,我们想概括一下
cart\u-fun
,我们想要的不是
cart\u-fun列表1-list2
,而是
cart\u-fun修饰符列表1-list2
,其中
modifier
只是一个函数。。。所以,没问题,让我们更改这部分代码:

让购物车乐趣修改器列表1列表2=
让进程列表2 fst acc=
List.fold_左
(趣味snd_acc y->(修饰符XY)::snd_acc)
fst_acc
清单2
在里面
让result=List.fold\u left process\u List\u 2[]list1 in
List.rev结果
瞧!如您所见,不需要太多修改。请记住,在OcAML中,可以考虑一个变量将包含一个函数;太酷了

顺便说一句,您想要捕获的“一般行为”看起来很像我们所说的“理解”(比如Python和Haskell)。自OCaml 4.10以来,列表模块中有一个函数,允许您轻松编写理解:
val concat_map:('a->'b list)->'a list->'b list
,其效果与映射a列表相同,生成b列表并将列表展平为b列表。 因此,您可以将笛卡尔积视为:

让购物车乐趣修改器列表1列表2=
List.concat_地图(乐趣x->
List.concat_地图(乐趣y->
[修饰符x y]
)清单2
)清单1
但正如你所看到的。。。它的可读性不比以前强多少了!幸运的是,除了将函数作为参数传递外,OCaml还允许您描述自己的运算符。例如,这里我们可以描述一个操作符来简化
concat\u map
的链接,我们可以随机调用它<代码>>=:

let(>>=)list f=list.concat\u映射f list
让购物车乐趣修改器列表1列表2=
列表1>>=有趣的x->
列表2>>=fun y->[修改器x y]
太棒了,我们能更深入地了解可读性吗?当然,自OCAML4.08以来,您可以定义
let
操作符。因此,定义自己的
带有后缀。例如,在这里,让我们定义
let*
(这与
>>=
完全相同)

let(let*)list f=list.concat\u map f list
(*因此,`let*x=l in gx`与`l>>=fun x->gx`*相同)
很好不

现在,我们可以重写我们的示例:

让购物车乐趣修改器列表1列表2=
设*x=list1英寸
设*y=list2英寸
[修饰符x y]
瞧!甚至:

让购物车乐趣修改器列表1列表2=
让进程列表2 fst acc=
List.fold_左
(趣味snd_acc y->(修饰符XY)::snd_acc)
fst_acc
清单2
在里面
让result=List.fold\u left process\u List\u 2[]list1 in
List.rev结果
是“更直接”吗?我觉得很高兴看到OCaml的表现力!
我希望我能帮助你,祝你度过愉快的一天

你所说的“功能替代”是什么意思?您似乎知道如何调用函数,如何定义命名函数和匿名函数,以及如何将函数作为参数传递给另一个函数。例如,在
List.fold_left
中,您认为函数参数在“inside”中是什么样子的,如果你真的写了这段代码,那应该不会有问题:这里你应用的函数就是
funxy->x*y
,所以在我看来,推广这段代码并不难。我唯一能帮你做的就是回答,因为你已经完成了所有的工作。。。