如何构造 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
(...)
在 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
(...)