[英]generic function in F#
I'm writing some kind of serialization library (for purpose of learning F#). 我正在编写某种序列化库(用于学习F#)。 And now I stuck with this:
现在我坚持这个:
Suppose we already have serialization functions for some basic types: 假设我们已经有一些基本类型的序列化函数:
type StoreOps =
static member inline store(x:int) = ...
static member inline store(x:int64) = ...
static member inline store(x:float) = ...
static member inline store(x:float32) = ...
static member inline store(x:bool) = ...
static member inline store(x:string) = ...
....
Now I want to implement generic function to store any array of basic types: 现在我想实现泛型函数来存储任何基本类型的数组:
let inline store(x:'T[]) =
x |> Array.iter StoreOps.store
, but compiler can't compile it (error message says: A unique overload for method 'store' could not be determined based on type information prior to this program point
). ,但编译器无法编译它(错误消息说:
A unique overload for method 'store' could not be determined based on type information prior to this program point
)。
What is a right way to implement such functions in F#? 在F#中实现这些功能的正确方法是什么? Because I don't want to copy-paste N equal functions for
int[]
, bool[]
, float[]
... 因为我不想为
int[]
, bool[]
, float[]
复制粘贴N个相等的函数...
First of all, you probably don't need inline
on the definitions which take arguments of a particular type. 首先,您可能不需要
inline
带有特定类型参数的定义。 Secondly, the short answer is probably "there's no good way to do that". 其次,简短的回答可能是“没有好办法”。 However, if you're willing to tolerate horrible hacks, you can do something like:
但是,如果你愿意忍受可怕的黑客行为,你可以做以下事情:
type StoreOps =
... // everything you've currently got
let inline storeArray< ^t, ^u when (^t or ^u) : (static member store : ^u -> unit)> arr =
arr
|> Array.iter (fun x -> ((^t or ^u) : (static member store : ^u -> unit) x))
type StoreOps with
static member inline store arr = storeArray<StoreOps,_> arr
You can also make the storeArray
helper private (using let inline private storeArray...
if you don't want it exposed. 您还可以将
storeArray
助手storeArray
私有(使用let inline private storeArray...
如果您不希望它暴露。
One workaround is passing store
functions as a parameter in a generic function: 一种解决方法是将
store
函数作为参数传递给泛型函数:
type StoreOps =
static member inline store (x: int) = ...
static member inline store (x: int64) = ...
static member inline store (x: float) = ...
static member inline store (x: float32) = ...
static member inline store (x: bool) = ...
static member inline store (x: string) = ...
static member storeArray xs f =
xs |> Array.iter f
....
// The compiler chooses the right overload based on types of array elements
StoreOps.storeArray [|100; 200|] StoreOps.store
StoreOps.storeArray [|100L; 200L|] StoreOps.store
You can do it this way: 你可以这样做:
type StoreOps = StoreOps with
static member ($) (StoreOps,x:int) = (* code for storing *) ()
static member ($) (StoreOps,x:int64) = (* code for storing *) ()
static member ($) (StoreOps,x:float) = (* code for storing *) ()
static member ($) (StoreOps,x:float32) = (* code for storing *) ()
static member ($) (StoreOps,x:bool) = (* code for storing *) ()
static member ($) (StoreOps,x:string) = (* code for storing *) ()
let inline store(x:_[]) = Array.iter (fun a -> StoreOps $ a) x
It will generate the constraints for you automatically. 它会自动为您生成约束。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.