如何构造F#元组类型?

时间:2015-07-15 16:16:26

标签: f# c#-to-f# r.net

在F#中给出以下类型

type Message = string * AsyncReplyChannel<SymbolicExpression>

我该如何构建它?在F# for fun and profit上有很棒的东西,但我找不到如何构建新的'代数数据类型'Message

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

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

我正在尝试将MailboxProcessor公开给C#,并试图保留与C#代码不同的F#特定类型。因此,我尝试仅接受一个字符串并重新设置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))是:

  

未定义值或构造函数消息

Signature

2 个答案:

答案 0 :(得分:4)

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

您正在寻找的可能是它的记录类型:

  

type Message = {str:String;表达式:AsyncReplyChannel&lt; SymbolicExpression&gt; }

然后你只能通过明确命名字段

来构建它
  

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

答案 1 :(得分:3)

您的消息定义只是元组的类型别名。编译器将类型视为等效类型 - 因此您有时可以在工具提示中看到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
  (...)