意外的输出类型

时间:2017-05-11 09:28:50

标签: recursion f#

我正在用F#练习。我正在尝试创建一个简单的程序,能够找到几个素数,总和,等于自然数输入。这是哥德巴赫猜想。一对素数就足够了。我们假设输入为偶数。

我首先创建了一个函数来检查数字是否为素数:

'!!!' {
    'Tillykke du har vundet 50 dollarz'
    $vundet+= 50
    $history += 'Tillykke du har vundet 50 dollarz'
}

然后,我试图开发一个函数,(a)查找素数,(b)将它们的和与输入'z'进行比较,(c)在找到两个数字时返回一个元组。该功能不应该是正确的,但我会得到这个问题背后的原因:

let rec isPrime (x: int) (i: int) :bool =
    match x % i with
    | _ when float i > sqrt (float x)   -> true
    | 0                                 -> false
    | _                                 -> isPrime x (i + 1)

问题:即使我指定输出应该是元组let rec sumPrime (z: int) (j: int) (k: int) :int * int = match isPrime j, isPrime k with | 0, 0 when j + k > z -> (0, 0) | 0, 0 -> sumPrime (j + 1) (k + 1) | _, 0 -> sumPrime j (k + 1) | 0, _ -> sumPrime (j + 1) k | _, _ -> if j + k < z then sumPrime (j + 1) k elif j + k = z then (j, k) 编译器抗议,声称预期输出应该是:int * int类型。遇到麻烦时,我通常会提到我喜欢的F# for fun and profit,但这次我找不到问题所在。任何建议都非常感谢。

1 个答案:

答案 0 :(得分:4)

您的代码有三个我发现的问题:

  1. 您的isPrime会返回bool(正如您指定的那样),但match中的sumPrime表达式与整数相匹配(在F#中) ,布尔值false 与整数值0相同。您的match表达式应如下所示:

    match isPrime j, isPrime k with
    | false, false when j + k > z   -> (0, 0)
    | false, false                  -> ...
    | true,  false                  -> ...
    | false, true                   -> ...
    | true,  true                   -> ...
    
  2. if...elif案例中有true, true个表达式,但没有最终else。默认情况下,else表达式的最终if会返回()类型unit。因此,一旦您解决了第一个问题,您就会发现F#抱怨int * intunit之间的类型不匹配。您需要在最终匹配案例中添加else条件,以说明如果j + k > z该怎么做。

  3. 您反复调用sumPrime函数,该函数只需两个参数即可获取三个参数。这在F#中是完全合法的,因为它是一种俗语:用两个参数调用sumPrime会产生类型int -> int * int:一个函数,它接受一个int并返回一个元组int秒。但那不是你真正想做的事情。确保在所有递归调用中为z指定值。

  4. 通过这三项更改,您可能会看到编译器错误消失。