oph*_*axo 4 functional-programming average sml
我最近的任务是计算标准机器学习中一组(由输入给出)的平均值。
这个想法是有一个像下面这样的函数,你输入一个实数列表并接收这些数字的平均值(也是一个实数),这样当你输入函数时终端会给出这个作为返回答案:
average = fn : real list -> real
Run Code Online (Sandbox Code Playgroud)
我们也在教程中讨论过这个问题,但我想知道在标准机器学习中创建这样的函数时是否有某种技巧。
提前致谢!
将数字相加并除以长度。简单的递归sum通常是您在任何 SML 教程中都会看到的第一个示例之一。您需要具有sum评估为的空列表基础情况,0.0而不是0确保返回类型是real. 定义sum函数后,您可以average使用sum内置length函数在 1 行中定义。一个微妙之处在于,SML 不允许实数除以整数。Real.fromInt在将总和除以它之前,您可以在长度上使用转换函数。将同一个列表传递两次会有些低效,一次是求和,一次是计算它的长度,但是当你第一次学习这门语言时,没有理由担心这些事情。
关于编辑:由于您找到了一个自然的解决方案并在评论中分享了它,这里有一个更惯用的版本,它计算一次遍历列表的平均值:
fun average nums =
let
fun av (s,n,[]) = s/Real.fromInt(n)
| av (s,n,x::xs) = av (s+x,n+1,xs)
in
av (0.0, 0, nums)
end;
Run Code Online (Sandbox Code Playgroud)
它通过定义一个帮助函数来完成繁重的工作。这些在函数式编程中被广泛使用。在没有可变状态的情况下,一个常见的技巧是显式地将数量作为参数传递,这些数量将被命令式语言中的相应循环连续修改。这些参数通常被调用,accumulators因为它们通常会累积增长列表、运行总和、运行产品等。这里s和n是累加器,具有s元素的总和和n列表的长度。在基本情况下,(s,n,[])没有什么可累积的,因此返回最终答案。在非基情况下(s,n,x::xs),s和n被适当修改并与列表的尾部一起传递给辅助函数。的定义av是尾递归的,因此将以循环的速度运行而不增加堆栈。整个average函数唯一需要做的就是用适当的初始值调用辅助函数。这let ... helper def ... in ... helper called with start-up values ...end是一个常用的习惯用法,用于防止程序的顶层被辅助函数弄乱。