0

给定 F# 中的以下类型

type Message = string * AsyncReplyChannel<SymbolicExpression>

我该如何构建它?F# 上的好东西是为了乐趣和利润,但我找不到如何构造新的“代数数据类型” Message

这是我正在尝试做的事情:

member x.Evaluate(expression: string, ?timeout) : SymbolicExpression =        
    agent.PostAndReply(fun c -> Message (expression,c), ?timeout=timeout) 

我正在尝试向MailboxProcessorC# 公开,并尝试使尽可能多的 F# 特定类型远离 C# 代码。因此,我试图只接受一个字符串并返回一个SymbolicExpression类型(来自RDotNet命名空间)。

更新

好的 - 这是完整的来源。

open RDotNet

type Message = string * AsyncReplyChannel<SymbolicExpression>

type RInterfaceAgent(dllpath:string, rhome:string) =
    let engine = 
        RDotNet.REngine.SetEnvironmentVariables(dllpath,rhome)
        RDotNet.REngine.GetInstance()

    let agent = MailboxProcessor<Message>.Start(fun inbox ->
        let rec messageLoop n = async {
            let! (msg, channel) = inbox.Receive()
            engine.Evaluate(msg) |> channel.Reply
            do! messageLoop (n+1)
        }
        messageLoop 0
    )      

    member x.Evaluate(ex: string, ?timeout) : SymbolicExpression =        
        agent.PostAndReply((fun c -> Message (ex, c)), ?timeout=timeout)

这部分的错误信息:(fun c -> Message (ex, c))是:

未定义值或构造函数 Message

签名

4

2 回答 2

4

您定义它的方式Message只是一个别名,Tuple<String, AsyncReplyChannel<SymbolicExpression>>因此它没有显式构造函数,指定对的任何元组都是消息。您可以只返回 a (expression,c),而不是Message (expression,c)

您正在寻找的可能是使其成为记录类型:

类型消息 = {str:字符串;表达式:AsyncReplyChannel<SymbolicExpression> }

然后你只能通过显式命名字段来构建它

{str=... ; 表达式 = ... }

于 2015-07-15T16:47:06.770 回答
3

您的消息定义只是元组的类型别名。编译器将类型视为等价 - 因此您有时可以Message在工具提示中看到,有时在扩展定义中看到。

type Message = string * AsyncReplyChannel<SymbolicExpression>

假设这是 type 并且agent是 type MailboxProcessor<Message>,以下将其发送到代理的方式应该可以工作:

member x.Evaluate(ex: string, ?timeout) : SymbolicExpression =        
    agent.PostAndReply((fun c -> (ex, c)), ?timeout=timeout)

该位(ex, c)只是创建一个元组(就是这样Message)。请注意,您需要 lambda 函数周围的括号(屏幕截图中缺少该括号)。

此外,不幸的是,F# 和 C# 中的可选参数的工作方式不同。因此,如果您正在编写 C# 友好的 API,则需要使用 C# 样式的可选参数,大致如下所示:

open System.Runtime.InteropServices

member x.Evaluate(ex:string, [<Optional>]timeout:Nullable<int>) = 
  let timeout = if timeout.HasValue then Some(timeout.Value) else None
  (...)
于 2015-07-15T17:21:27.637 回答