SML - 使用模式匹配进行交替求和

问题描述 投票:0回答:4

我正在编写一个程序,它接受

int
列表并返回它们的交替和的值。

Input: [1,2,3,4]
Output: 1 + (-2) + 3 + (-4)

下面是我尝试为此编写的代码,但我不断收到错误

syntax error: inserting ORELSE

我的

if then else
声明看起来正确,所以我不确定是什么导致了错误

fun alternate([]) = 0
  | alternate(x::xs, count) = 
        count = count + 1
        if count mod 2 == 0 then (~x) + alternate(xs)
        else x + alternate(xs)
list sml
4个回答
2
投票

此错误是由于

count = count + 1
if ... else ...
是多个表达式导致的。如果要执行多个表达式,可以这样写代码:

(expression1;
 expression2;
     ...
 expressionN);

您的代码中还有另外两个错误。
1. 函数不同模式子句中的参数类型不同

alternate

2. 在 SML 中,
=
表示相等,而不是
==

所以正确的解决方案可能如下所示:

fun alternate([]) = 0
  | alternate(x::xs) =
      let 
        fun alt([], count) = 0
          | alt(x::xs, count) =
              if count mod 2 = 0 then x + alt(xs, count+1)
              else (~x) + alt(xs, count+1)
      in 
        alt(x::xs, 0)
      end;

1
投票

基于我之前的答案,我建议实施sum

val sum = foldr (op +) 0;

为了完整起见,从此处复制该答案中的

alternate

 函数,并修复一个小错误:

fun alternate l = let fun alternate1 [] = [] | alternate1 (x::xs) = x :: alternate2 xs and alternate2 [] = [] | alternate2 (x::xs) = (~x) :: alternate1 xs in alternate1 l end

然后你可以非常简单地定义

alternate_sum

val alternate_sum = sum o alternate

当然会有以表演为名的反对意见。 Haskell 能够跨这些类型的调用执行森林砍伐/融合优化,因为它了解函数的纯度;标准机器学习并不

需要这些优化,尽管有些实现可能会尝试它们,我不知道。

这个特定问题的开销可能荒谬,也可能不荒谬,但我认为无论如何,它都是函数式编程原理的一个很好的例子:从更简单、无可挑剔的行为构建复杂的行为。这个版本的“举证责任”几乎全在

alternate

。 @SunsetRider 的版本很好(它可能会表现得更好),但你可能会说代码更加“单一”。

另外,@SunsetRider 的代码比需要的要复杂一点,这个版本就足够了:

fun alternate l = let fun alt([], count) = 0 | alt(x::xs, count) = if count mod 2 = 0 then x + alt(xs, count+1) else (~x) + alt(xs, count+1) in alt(l, 0) end

除了 @SunsetRider 所说的之外,还有一条评论:一般来说,在函数式语言中

x = x + 1

 和其他突变有点代码味道。您可以看到,在他们的代码中,他们多次使用 
count+1
。从功能上思考,重要的是表达式的计算结果,而不是变量的状态,因此传递的值至关重要。这可以追溯到Pieter Hartel
Functional C这本优秀且被严重低估的书开头的superb定义:

函数式和命令式范式从不同的角度运作。函数范式基于“表达式求值”以及将变量绑定到值。基本的程序短语是表达式,计算表达式的目的是产生一个值。子表达式的求值顺序不会影响结果值。

命令式范例基于“语句的执行”并拥有一个存储,语句可以在其中留下其结果。基本的程序短语是语句;执行语句的目的是改变存储。语句执行的顺序确实会影响存储中的结果值。存储中当前的一组值称为程序的

state

这里有替代解决方案

altSum :: (Num a) => [a] -> a altSum (x:[]) = x altSum (x:y:xs) = x - y + altSum xs

0
投票

`altsum n = x1 -x2 +x3 -x4 +... +xn = x1 -(x2 -x3 +x4 +...+xn) = x1 - altsum(n-1)

有趣的altsum [] = 0
|代数 x::xs = x - 代数 xs`

0
投票

© www.soinside.com 2019 - 2024. All rights reserved.