我有一本操作字典:
type INumerics<'T> =
abstract Zer : 'T
abstract Add : 'T * 'T -> 'T
abstract Sub : 'T * 'T -> 'T
abstract Mul : 'T * 'T -> 'T
abstract Div : 'T * 'T -> 'T
abstract Neq : 'T * 'T -> bool
使用辅助功能:
let inline add (x : 'T) (y : 'T) : 'T = (+) x y
let inline sub (x : 'T) (y : 'T) : 'T = (-) x y
let inline mul (x : 'T) (y : 'T) : 'T = (*) x y
let inline div (x : 'T) (y : 'T) : 'T = (/) x y
let inline neq (x : 'T) (y : 'T) : bool = (<>) x y
然后我们有一个使用 MailboxProcessor 代理的简单计算器:
type Agent<'T> = MailboxProcessor<'T>
type CalculatorMsg<'T> =
| Add of 'T * 'T * AsyncReplyChannel<'T>
| Sub of 'T * 'T * AsyncReplyChannel<'T>
| Mul of 'T * 'T * AsyncReplyChannel<'T>
| Div of 'T * 'T * AsyncReplyChannel<'T>
type CalculatorAgent< ^T when ^T : (static member get_Zero : unit -> ^T)
and ^T : (static member Zero : ^T)
and ^T : (static member (+) : ^T * ^T -> ^T)
and ^T : (static member (-) : ^T * ^T -> ^T)
and ^T : (static member (*) : ^T * ^T -> ^T)
and ^T : (static member (/) : ^T * ^T -> ^T)
and ^T : equality >() =
let agent =
let ops =
{ new INumerics<'T> with
member ops.Zer = LanguagePrimitives.GenericZero<'T>
member ops.Add(x, y) = (x, y) ||> add
member ops.Sub(x, y) = (x, y) ||> sub
member ops.Mul(x, y) = (x, y) ||> mul
member ops.Div(x, y) = (x, y) ||> div
member ops.Neq(x, y) = (x, y) ||> neq }
Agent<CalculatorMsg<'T>>.Start(fun inbox ->
let rec loop () =
async {
let! msg = inbox.TryReceive()
if msg.IsSome then
match msg.Value with
| Add (x, y, rep) ->
printfn "Adding %A and %A ..." x y
let res = ops.Add(x, y)
res |> rep.Reply
return! loop()
| Sub (x, y, rep) ->
printfn "Subtracting %A from %A ..." y x
let res = ops.Sub(x, y)
res |> rep.Reply
return! loop()
| Mul (x, y, rep) ->
printfn "Multiplying %A by %A ... " y x
let res = ops.Mul(x, y)
res |> rep.Reply
return! loop()
| 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()
else
return! loop()
}
loop()
)
// timeout = infinit => t = -1
let t = 1000
member inline this.Add(x, y) =
agent.PostAndTryAsyncReply((fun rep -> Add (x, y, rep)), t)
|> Async.RunSynchronously
member inline this.Subtract(x, y) =
agent.PostAndTryAsyncReply((fun rep -> Sub (x, y, rep)), t)
|> Async.RunSynchronously
member inline this.Multiply(x, y) =
agent.PostAndTryAsyncReply((fun rep -> Mul (x, y, rep)), t)
|> Async.RunSynchronously
member inline this.Divide(x, y) =
agent.PostAndTryAsyncReply((fun rep -> Div (x, y, rep)), t)
|> Async.RunSynchronously
作为一个使用示例,我们有:
let calculatorAgentI = new CalculatorAgent<int>()
(2, 1) |> calculatorAgentI.Add
(2, 1) |> calculatorAgentI.Subtract
(2, 1) |> calculatorAgentI.Multiply
(2, 1) |> calculatorAgentI.Divide
(2, 0) |> calculatorAgentI.Divide
问题是 Add and Multiply 和 Last Divide 工作正常:
>
Adding 2 and 1 ...
val it : int option = Some 3
>
Multiplying 1 by 2 ...
val it : int option = Some 2
>
Dividing 2 by 0 ...
#DIV/0
val it : int option = None
一旦我们使用 Subtract 和 first Divide int option = None
,我就会遇到麻烦,以下是我从任何操作中得到的唯一输出:
>
val it : int option = None
只要我仔细考虑,我无法弄清楚“减”/“除”部分或“接收”/“回复”操作是否有问题。