如何定义F#f
中仅接受限制为x
或int32
类型的参数int64
的函数?
答案 0 :(得分:7)
这是一种在编译时限制它的方法。首先创建函数的通用版本:
let inline twice x = x + x
然后使用重载决策和静态成员约束将其限制为所需类型:
type T = T with
static member ($) (T, x:int ) = twice x
static member ($) (T, x:int64) = twice x
let inline restrictedTwice x = T $ x
试验:
restrictedTwice 4 //val it : int = 8
restrictedTwice 5L //val it : int64 = 10L
restrictedTwice 5u // doesn't compile
答案 1 :(得分:4)
如果您可以将函数定义为类方法,则可以使用常规的.NET方法重载:
type Foo =
static member Bar (x : int) = sprintf "32-bit integer: %i" x
static member Bar (x : int64) = sprintf "64-bit integer: %i" x
FSI示例:
> Foo.Bar 42;;
val it : string = "32-bit integer: 42"
> Foo.Bar 42L;;
val it : string = "64-bit integer: 42"
如果您需要将函数作为let-bound函数,则不能使用方法重载。 Instead, you can define a discriminated union将输入选项限制为int
或int64
:
type DUInt =
| NormalInt of int
| BiggerInt of int64
你应该想出一些更好的名字,但我选择避免使用Int32
和Int64
因为它会使代码难以阅读,因为System
命名空间也定义了这些名称为类型。
使用这种区分联合,您可以编写一个将该类型的值作为输入的函数:
let foo = function
| NormalInt x -> sprintf "32-bit integer: %i" x
| BiggerInt x -> sprintf "64-bit integer: %i" x
此函数的类型为DUInt -> string
。
FSI示例:
> foo (NormalInt 42);;
val it : string = "32-bit integer: 42"
> foo (BiggerInt 42L);;
val it : string = "64-bit integer: 42"