在F#中是否可能存在重载操作符,其中操作数是函数?
例如(使用Chessie):
module AsyncTrialOperators =
type Ops=
/// Left-to-right Kleisli composition
static member (>=>) (f:'a -> AsyncResult<'b,_>, g:'b -> AsyncResult<'c,_>) =
fun x ->
asyncTrial {
let! y = f x
let! z = g y
return z }
/// Left-to-right Kleisli composition
static member (>=>) (f:'a -> AsyncResult<'b,_>, g:'b -> Result<'c,_>) =
fun x ->
asyncTrial {
let! y = f x
let! z = g y
return z }
// Example usage (doesn't compile)
let f x = ok x
let g x = fail x
let z = f >=> g给出以下错误:FS0043 Expecting a type supporting the operator '>=>' but given a function type. You may be missing an argument to a function.
发布于 2018-04-16 11:09:48
它不起作用,因为Ops不是参数的一部分。
您可以使用将其中一个参数移动到lambda的技巧,然后使用空参数来接收容器类型的虚拟参数:
#r @"c:\packages\chessie.0.6.0\lib\net40\Chessie.dll"
open Chessie
open Chessie.ErrorHandling
type Ops=
/// Left-to-right Kleisli composition
static member (>=>) (_:Ops, g:'b -> Result<'c,_>) =
fun (f:'a -> AsyncResult<'b,_>) x ->
asyncTrial {
let! y = f x
let! z = g y
return z }
/// Left-to-right Kleisli composition
static member (>=>) (_:Ops, g:'b -> AsyncResult<'c,_>) =
fun (f:'a -> AsyncResult<'b,_>) x ->
asyncTrial {
let! y = f x
let! z = g y
return z }然后可以在全局级别重新定义>=>:
let inline (>=>) x y = (Unchecked.defaultof<Ops> >=> y) x但是现在您会意识到传递错误的参数,f必须是AsyncResult<_,_>类型的,因为我不熟悉chessie,所以我将使用一个虚拟函数:
let f x = Unchecked.defaultof<AsyncResult<int,int>>
let g x = fail x现在还有一个细节,为了避免对值的限制,您必须在两边添加x:
let z x = (f >=> g) x这是可行的,但我强烈建议你不要这样设计。
如果你问我,超载,特别是在全球层面,必须遵循一些规则才能保持一致。这种Ad重载设计a C#将不能很好地工作,因为您添加了更多的东西,很快就会遇到类型推断不知道要做什么的情况,甚至连代码的读者都不知道。
如果您想使用泛型(且行为良好) >=>,请查看在F#+中定义的
https://stackoverflow.com/questions/49854872
复制相似问题