如何参数化F#类

时间:2015-10-16 16:07:34

标签: f#

下面的类是公开的异步邮箱处理器的包装器 C#程序集的一些操作。但是,我不想要几个

Map<string,int>

实例,我需要几个不同的Map&lt;'K,'V&gt; '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

顺便说一句,这是原型质量代码,显然不是那么好。

1 个答案:

答案 0 :(得分:3)

我不确定我是否完全理解了这个问题,但是如果你想创建一个可以与不同类型的值一起使用的类型,你可以将该类定义为泛型:

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)

要使其工作,您需要避免将键和类型的类型限制为特定类型的代码。在您的情况下,lookup返回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"