我有一本操作词典:
类型INumerics<’T> = 抽象Zer:’T 摘要添加:’T *’T - > “T 抽象子:’T *’T - > “T 抽象Mul:’T *’T - > “T 抽象Div:……
这种行为似乎是一种不规则或错误。我也期待这对所有操作来说都是一样的。
无论如何,您可以通过捕获来解决此问题 ops 在静态内联成员中(而不是在类型上使用静态解析的类型参数)。以下工作对我来说很好:
ops
type CalculatorAgent<'T>(ops:INumerics<'T>) = let agent = Agent<CalculatorMsg<'T>>.Start(fun inbox -> let rec loop () = async { let! msg = inbox.TryReceive() match msg with | Some(Add (x, y, rep)) -> printfn "Adding %A and %A ..." x y let res = ops.Add(x, y) res |> rep.Reply return! loop() | Some(Sub (x, y, rep)) -> printfn "Subtracting %A from %A ..." y x let res = ops.Sub(x, y) res |> rep.Reply return! loop() | Some(Mul (x, y, rep)) -> printfn "Multiplying %A by %A ... " y x let res = ops.Mul(x, y) res |> rep.Reply return! loop() | Some(Div (x, y, rep)) -> printfn "Dividing %A by %A ..." x y if ops.Neq(y, ops.Zer) then let res = ops.Div(x, y) res |> rep.Reply else printfn "#DIV/0" return! loop() | _ -> return! loop() } loop() ) // timeout = infinit => t = -1 let t = 1000 member this.Add(x, y) = agent.PostAndTryAsyncReply((fun rep -> Add (x, y, rep)), t) |> Async.RunSynchronously member this.Subtract(x, y) = agent.PostAndTryAsyncReply((fun rep -> Sub (x, y, rep)), t) |> Async.RunSynchronously member this.Multiply(x, y) = agent.PostAndTryAsyncReply((fun rep -> Mul (x, y, rep)), t) |> Async.RunSynchronously member this.Divide(x, y) = agent.PostAndTryAsyncReply((fun rep -> Div (x, y, rep)), t) |> Async.RunSynchronously type CalculatorAgent = static member inline Create() = let ops = { new INumerics<_> with member ops.Zer = LanguagePrimitives.GenericZero<_> member ops.Add(x, y) = x + y member ops.Sub(x, y) = x - y member ops.Mul(x, y) = x * y member ops.Div(x, y) = x / y member ops.Neq(x, y) = x <> y } CalculatorAgent<_>(ops) let calculatorAgentI = CalculatorAgent.Create<int>() (2, 1) |> calculatorAgentI.Add (2, 1) |> calculatorAgentI.Subtract (2, 1) |> calculatorAgentI.Multiply (2, 1) |> calculatorAgentI.Divide (2, 0) |> calculatorAgentI.Divide
也就是说,我认为你真正需要通用数字代码的情况非常罕见 - 所以我怀疑最好避免完全引入所有这些复杂性,只需编写特定数字类型的代码。
在附加调试器的情况下运行此代码,您将看到在尝试运行时遇到System.NotSupportedException sub 代理内部的功能:
sub
System.NotSupportedException occurred HResult=0x80131515 Message=Specified method is not supported. Source=FSI-ASSEMBLY StackTrace: at FSI_0002.ops@60.FSI_0002-INumerics`1-Sub(T X1, T X2)
你得到的原因 val it : int option = None 是因为你指定了1秒的超时,并且在抛出异常之后你正在尝试。
val it : int option = None
打电话给 sub 函数直接工作正常,但通过调用它 CalculatorAgent 上课没有。这是因为在这种情况下类型参数是在类上定义的,并且在F#中对类的结构类型约束的使用存在限制。我建议你继续阅读 静态分辨的类型参数 和他们的局限。
CalculatorAgent