如何构造 F# 元组类型?

How to construct F# tuple type?

在 F# 中给定以下类型

type Message = string * AsyncReplyChannel<SymbolicExpression>

我该如何构建它? F# for fun and profit 的好东西,但我找不到如何构建新的 'algebraic data type' Message

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

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

我正在尝试将 MailboxProcessor 公开给 C# 并尽量让 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))是:

The value or constructor Message is not defined

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

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

type Message = {str: String; expression: AsyncReplyChannel<SymbolicExpression> }

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

{str=... ;expression = ... }

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

type Message = string * AsyncReplyChannel<SymbolicExpression>

假设这是类型并且 agent 是类型 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
  (...)