Algorithm 用OCAML进行函数式编程

Algorithm 用OCAML进行函数式编程,algorithm,functional-programming,ocaml,Algorithm,Functional Programming,Ocaml,我是函数式编程新手,我正在尝试使用OCAML实现一个基本算法,这是我目前正在学习的课程 我正在尝试实现以下算法: 条目: -E:非空整数集 -s:一个整数 -d:不同于0的正浮点 输出: -T:包含在E中的一组整数 m函数式编程的基本技巧是,尽管不能修改任何变量的值,但可以使用不同的参数调用函数。在从命令式思维方式转换的初始阶段,您可以想象将要修改的每个变量都转换为函数的参数。要修改变量,可以使用所需的新值递归调用函数 此技术将用于“修改”变量m。将m视为函数参数 您已经将此技术用于acc。折叠

我是函数式编程新手,我正在尝试使用OCAML实现一个基本算法,这是我目前正在学习的课程

我正在尝试实现以下算法:

条目:
-E:非空整数集
-s:一个整数
-d:不同于0的正浮点
输出:
-T:包含在E中的一组整数


m函数式编程的基本技巧是,尽管不能修改任何变量的值,但可以使用不同的参数调用函数。在从命令式思维方式转换的初始阶段,您可以想象将要修改的每个变量都转换为函数的参数。要修改变量,可以使用所需的新值递归调用函数

此技术将用于“修改”变量
m
。将
m
视为函数参数


您已经将此技术用于
acc
。折叠中的每个调用都会获取旧值
acc
,并返回新值,然后将新值再次传递给函数。您可以想象将
acc
m
作为此内部函数的参数。

函数式编程的基本技巧是,尽管不能修改任何变量的值,但可以使用不同的参数调用函数。在从命令式思维方式转换的初始阶段,您可以想象将要修改的每个变量都转换为函数的参数。要修改变量,可以使用所需的新值递归调用函数

此技术将用于“修改”变量
m
。将
m
视为函数参数


您已经将此技术用于
acc
。折叠中的每个调用都会获取旧值
acc
,并返回新值,然后将新值再次传递给函数。您可以想象将
acc
m
作为此内部函数的参数。

假设定义了
list\u min
,您应该有条理地思考问题。假设您用一个列表表示一个集合。如果元素满足某些条件,则函数将获取此集合和一些参数,并返回原始集合的子集

现在,当我第一次读到这篇文章时,
List.filter
自动浮现在我的脑海中

List.filter : ('a -> bool) -> 'a list -> 'a list
但是您想修改
m
,这样就没有用了。了解何时可以使用库函数以及何时真正需要从头开始创建自己的函数非常重要。在处理
m
时,您可以清楚地使用
filter
作为参考,但这不是功能性的方法

首先,让我们关注您的谓词:

fun s d m e -> (float e) > (1. +. d)*.(float m) && (e <= s)
这就是初始的
m

然后,我将定义一个辅助函数,它将
m
作为参数读取,并将
l
作为原始集合,将
s
d
m
作为原始命令式代码中使用的变量

let rec f' l s d m =
  match l with
  | [] -> []
  | x :: xs -> if (predicate s d m x) then begin
                 x :: (f' xs s d x)
               end
               else
                 f' xs s d m in
f' l s d m
然后,对于集合中的每个元素,检查它是否满足谓词,如果满足,则再次调用函数,但将
m
的值替换为
x

最后,您可以从函数
f
调用
f'

let f (l: int list) (s: int) (d: float) =
  let m = list_min l in
  f' l s d m
创建类似于
列表的函数时要小心,如果列表为空,会发生什么情况?通常您会使用
选项
类型来处理这些情况,但您假设您处理的是一个非空集,所以这很好


在进行函数式编程时,重要的是要考虑函数式。模式匹配是超级推荐的,而指针/引用应该是最小的。我希望这是有用的。如果您有任何其他疑问或建议,请与我联系。

假设定义了
list\u min
,您应该有条不紊地思考问题。假设您用一个列表表示一个集合。如果元素满足某些条件,则函数将获取此集合和一些参数,并返回原始集合的子集

现在,当我第一次读到这篇文章时,
List.filter
自动浮现在我的脑海中

List.filter : ('a -> bool) -> 'a list -> 'a list
但是您想修改
m
,这样就没有用了。了解何时可以使用库函数以及何时真正需要从头开始创建自己的函数非常重要。在处理
m
时,您可以清楚地使用
filter
作为参考,但这不是功能性的方法

首先,让我们关注您的谓词:

fun s d m e -> (float e) > (1. +. d)*.(float m) && (e <= s)
这就是初始的
m

然后,我将定义一个辅助函数,它将
m
作为参数读取,并将
l
作为原始集合,将
s
d
m
作为原始命令式代码中使用的变量

let rec f' l s d m =
  match l with
  | [] -> []
  | x :: xs -> if (predicate s d m x) then begin
                 x :: (f' xs s d x)
               end
               else
                 f' xs s d m in
f' l s d m
然后,对于集合中的每个元素,检查它是否满足谓词,如果满足,则再次调用函数,但将
m
的值替换为
x

最后,您可以从函数
f
调用
f'

let f (l: int list) (s: int) (d: float) =
  let m = list_min l in
  f' l s d m
创建类似于
列表的函数时要小心,如果列表为空,会发生什么情况?通常您会使用
选项
类型来处理这些情况,但您假设您处理的是一个非空集,所以这很好


在进行函数式编程时,重要的是要考虑函数式。模式匹配是超级推荐的,而指针/引用应该是最小的。我希望这是有用的。如果您有任何其他疑问或建议,请与我联系。

谢谢您的回答,了解我应该如何处理此问题非常有用。谢谢您的回答,了解我应该如何处理此问题非常有用。谢谢您的回答,我同意您关于以下用法的看法,我认为我