简体   繁体   English

使用F#进行递归加法

[英]Recursive addition in F# using

I'm trying to implement the following recursive definition for addition in F# 我正在尝试为F#实现以下递归定义

m + 0 := m m + 0:= m

m + (n + 1) := (m + n) + 1 m +(n + 1):=(m + n)+1

I can't seem to get the syntax correct, The closest I've come is 我似乎无法正确理解语法,最近的是

let rec plus x y =                        
 match y with                     
 | 0 -> x;                        
 | succ(y) -> succ( plus(x y) );

Where succ n = n + 1. It throws an error on pattern matching for succ. succ n = n +1。在succ的模式匹配上引发错误。

I'm not sure what succ means in your example, but it is not a pattern defined in the standard F# library. 我不确定succ在您的示例中是什么意思,但这不是标准F#库中定义的模式。 Using just the basic functionality, you'll need to use a pattern that matches any number and then subtract one (and add one in the body): 仅使用基本功能,您将需要使用与任意数字匹配的模式,然后减去一个(并在正文中添加一个):

let rec plus x y =                         
 match y with                      
 | 0 -> x                     
 | y -> 1 + (plus x (y - 1))

In F# (unlike eg in Prolog), you can't use your own functions inside patterns. 在F#中(不同于Prolog),您不能在模式内部使用自己的函数。 However, you can define active patterns that specify how to decompose input into various cases. 但是,您可以定义活动模式 ,这些模式指定如何将输入分解为各种情况。 The following takes an integer and returns either Zero (for zero) or Succ y for value y + 1 : 以下代码取一个整数,并为值y + 1返回Zero (对于零)或Succ y

let (|Zero|Succ|) n = 
  if n < 0 then failwith "Unexpected!"
  if n = 0 then Zero else Succ(n - 1)

Then you can write code that is closer to your original version: 然后,您可以编写更接近原始版本的代码:

let rec plus x y =
  match y with
  | Zero -> x
  | Succ y -> 1 + (plus x y)

As Tomas said, you can't use succ like this without declaring it. 正如Tomas所说,您不能在不声明的情况下使用succ What you can do is to create a discriminated union that represents a number: 您可以做的是创建一个代表数字的有区别的联合:

type Number = 
| Zero
| Succ of Number

And then use that in the plus function: 然后在plus函数中使用它:

let rec plus x y =
 match y with
 | Zero -> x
 | Succ(y1) -> Succ (plus x y1)

Or you could declare it as the + operator: 或者,您可以将其声明为+运算符:

let rec (+) x y =
 match y with
 | Zero -> x
 | Succ(y1) -> Succ (x + y1)

If you kept y where I have y1 , the code would work, because the second y would hide the first one. 如果将y放在我有y1 ,则代码将起作用,因为第二个y将隐藏第一个。 But I think doing so makes the code confusing. 但是我认为这样做会使代码混乱。

type N = Zero | Succ of N

let rec NtoInt n =
  match n with
  | Zero -> 0
  | Succ x -> 1 + NtoInt x

let rec plus x y =
  match x with
  | Zero -> y
  | Succ n -> Succ (plus n y)

DEMO: 演示:

> plus (Succ (Succ Zero)) Zero |> NtoInt ;;
val it : int = 2
> plus (Succ (Succ Zero)) (Succ Zero) |> NtoInt ;;
val it : int = 3
let rec plus x y =
    match y with
    | 0 -> x
    | _ -> plus (x+1) (y-1)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM