The class below is a wrapper around an async MailboxProcessor that exposes a few operations to C# assemblies. However, I don't want just a few
下面的类是一个围绕异步邮箱处理器的包装器,它向c#程序集公开一些操作。然而,我不想要几个
Map<string,int>
instances, I need several different Map<'K,'V> instances where 'K and 'V vary. I hope I don't need a functor for that (it probably doesn't exist in F#).
实例,我需要几个不同的映射<'K,'V>实例,其中'K和'V变化。我希望我不需要这个函数(它可能不存在于f#中)。
module Flib.AsyncEvents
open System.Collections.Generic
type KVcoll = Map<string,int>
type Msg = Request of string * int option | Fetch of AsyncReplyChannel<KVcoll> | Clear
#nowarn "40"
type myAgent () = class
let dictAgent = MailboxProcessor.Start(fun inbox->
let dict = ref Map.empty
let rec loop = async {
let! msg = inbox.Receive()
match msg with
| Request (key, Some value) -> dict := Map.add key value !dict
| Request (key, None) -> dict := Map.remove key !dict
| Fetch(reply) -> reply.Reply(!dict)
| Clear -> dict := Map.empty
return! loop
}
loop)
member this.add(key, value) = dictAgent.Post (Request (key, Some value))
member this.del(key) = dictAgent.Post (Request(key, None))
member this.fetch() = dictAgent.PostAndReply((fun reply -> Fetch(reply)), timeout = 9000)
member this.lookup(key) = try 0, Map.find key (this.fetch()) // success
with | :? KeyNotFoundException -> -1, 0 // failure
member this.size() = this.fetch().Count
member this.clear() = dictAgent.Post (Clear)
member this.print() =
this.fetch() |> Map.iter (fun k v -> printfn "%s => %d" k v)
printfn "done"
end
By the way, this is prototype quality code, clearly not as good as it can be.
顺便说一下,这是质量代码的原型,显然不是最好的。
1 个解决方案
#1
3
I'm not sure I understand the question fully, but if you want to create a type that can be used with different types of values, you can define the class as generic:
我不确定我是否完全理解这个问题,但是如果您想创建一种可以与不同类型的值一起使用的类型,您可以将类定义为泛型:
type Msg<'K, 'V when 'K : comparison> =
| Request of 'K * 'V option
| Fetch of AsyncReplyChannel<Map<'K, 'V>>
| Clear
type MyAgent<'K, 'V when 'K : comparison> () = class
let dictAgent = MailboxProcessor.Start(fun inbox->
let dict : Map<'K, 'V> ref = ref Map.empty
let rec loop = async {
// (same as before)
}
loop)
To make this work, you'll need to avoid code that restricts the type of keys and values to a particular type. In you case lookup
was returning 0
as the default value and print
was expecting strings. So you can replace those with something like:
要实现这一点,您需要避免将键和值的类型限制为特定类型的代码。在这种情况下,查找将返回0作为默认值,而print将等待字符串。所以你可以把它们替换成:
member this.lookup(key) = Map.tryFind key (this.fetch())
member this.print() =
this.fetch() |> Map.iter (fun k v -> printfn "%A => %A" k v)
printfn "done"
#1
3
I'm not sure I understand the question fully, but if you want to create a type that can be used with different types of values, you can define the class as generic:
我不确定我是否完全理解这个问题,但是如果您想创建一种可以与不同类型的值一起使用的类型,您可以将类定义为泛型:
type Msg<'K, 'V when 'K : comparison> =
| Request of 'K * 'V option
| Fetch of AsyncReplyChannel<Map<'K, 'V>>
| Clear
type MyAgent<'K, 'V when 'K : comparison> () = class
let dictAgent = MailboxProcessor.Start(fun inbox->
let dict : Map<'K, 'V> ref = ref Map.empty
let rec loop = async {
// (same as before)
}
loop)
To make this work, you'll need to avoid code that restricts the type of keys and values to a particular type. In you case lookup
was returning 0
as the default value and print
was expecting strings. So you can replace those with something like:
要实现这一点,您需要避免将键和值的类型限制为特定类型的代码。在这种情况下,查找将返回0作为默认值,而print将等待字符串。所以你可以把它们替换成:
member this.lookup(key) = Map.tryFind key (this.fetch())
member this.print() =
this.fetch() |> Map.iter (fun k v -> printfn "%A => %A" k v)
printfn "done"