简单的Add函数可使用整数和浮点数

时间:2019-11-09 19:32:59

标签: f#

我对F#还是很陌生,我正在尝试编写一些不区分浮点数和整数的代码,并将它们都视为“数字”。首先,我需要一个简单的“加”函数,该函数将两个数字相加,其中每个数字可以是整数或浮点数。

这是我目前的方法,一点都不优雅,这可能是由于我对F#的复杂性不了解所致。

type Number =
       | Integer of int
       | Float of float

   let add (a: Number, b: Number) : Number =
       match a with
        | Integer(a) ->
              match b with
                  | Integer(b) -> Integer(a + b)
                  | Float(b) -> Float(double a + b)
        | Float(a) ->
              match b with
                  | Integer(b) -> Float(a + double b)
                  | Float(b) -> Float(a + b)

这行得通,但是对于这样一个简单的功能,有很多代码。特别是,如果我还想要一个“减”功能,则必须复制/粘贴整个功能,然后将“ +”更改为“-”,这似乎效率很低。在F#中有更好的方法吗?

2 个答案:

答案 0 :(得分:2)

一种可能的方法可能是

// Generic function to reduce two numbers into a number
//  i reduces nested integers
//  f reduces nested floats
//  In order for i,f to be merged into single reducer
//  F# would have to support higher ranked types (I think)
//  but F# does not
let reduce i f (a: Number) (b: Number) : Number =
  match a, b with
  | Integer a, Integer b -> Integer (i a b)
  | Integer a, Float   b -> Float   (f (float a) b)
  | Float   a, Integer b -> Float   (f a (float b))
  | Float   a, Float   b -> Float   (f a b)

// Define common reducer functions
//  Operators +,-,* and / are parametric polymorphic
//  So the first ( + ) becomes an int -> int -> int
//  the second ( + ) becomes an float -> float -> float
let add       = reduce ( + ) ( + )
let subtract  = reduce ( - ) ( - )
let multiply  = reduce ( * ) ( * )
let divide    = reduce ( / ) ( / )

答案 1 :(得分:2)

应用inline关键字将导致F#在编译时使用静态解析类型参数(SRTP)自动生成两个函数(一个用于int,一个用于float)。

let inline add a b = a + b

add 5 6

add 5.2  5.8

此功能的类型如下所示。请注意,每个参数以及返回值都可以具有不同的类型(^ a,^ b或^ c)。 ^符号表示SRTP。

val inline add :
  a: ^a -> b: ^b ->  ^c
    when ( ^a or  ^b) : (static member ( + ) :  ^a *  ^b ->  ^c)

如果愿意,可以将参数和返回值都强制设置为相同的类型。

let inline add (a: ^a) (b: ^a) : ^a = a + b

此函数的签名为:

val inline add :
  a: ^a -> b: ^a ->  ^a when  ^a : (static member ( + ) :  ^a *  ^a ->  ^a)