我对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#中有更好的方法吗?
答案 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)