访问以其他类型

时间:2015-06-29 10:32:29

标签: f#

我在F#中建模协议。 协议声明有一个登录命令,它将用户名和密码作为参数,并且有一个不带参数的注销。 在协议将它们作为命令接受之前,命令必须用一些字符串post和prefix包装。

到目前为止,我有以下型号。 Command有一些与之关联的数据,在某些时候我想用post-和前缀包装给定的命令。 为此,我有一个名为FormattedCommand的新类型,它有一个命令,一个字符串表示命令和参数以及名为SendString的帖子/前缀。

当我通过调用formatCommand: command:Command -> FormattedCommand格式化命令的内容时,我想访问命令的CommandString,以便我可以附加帖子/前缀。我怎样才能做到这一点?

type CommandData = {
    CommandString : string;
    Parameters : string; }

type Command =
    | Login of CommandData
    | Logout of CommandData

type FormattedCommand = {
        Command : Command;
        SendString : string; }

let formatCommand (command:Command) =
    { Command = command; SendString = ?? }

3 个答案:

答案 0 :(得分:4)

如果我理解你的要求,我认为你可以使它更简单。

  

协议声明有一个登录命令,它将用户名和密码作为参数,   并且有一个不带参数的注销。

我会这样建模:

type Command =
   | Login of username:string * password:string
   | Logout
  

在协议接受命令作为命令之前,命令必须用一些字符串后缀和前缀包装。

我会这样建模:

type FormattedCommand = 
    FormattedCommand of string

我不明白为什么格式化命令需要知道原始命令。看起来你好像在混淆问题。 如果需要同时传递它们,请使用元组或制作简单的记录类型。

  

我想用post-和前缀包装给定的命令。

我会创建一个序列化命令的函数,如下所示:

let toFormattedCommand prefix postfix command =
    let commandStr =
        match command with
        | Login (username,password) -> 
            sprintf "%s|Login|%s|%s|%s" prefix username password postfix 
        | Logout ->
            sprintf "%s|Logout|%s" prefix postfix 
    FormattedCommand commandStr

我刚刚使用条形来分隔字段。显然,真正的协议会有所不同。

上述功能是通用的,但如果您愿意,可以使用默认前缀进行烘焙:

// bake in the defaults
let toFormattedCommandWithDefaults =
    toFormattedCommand "pre" "post"

然后你可以创建这样的例子:

let loginStr =
    Login("alice","123") 
    |> toFormattedCommandWithDefaults
// FormattedCommand "pre|Login|alice|123|post"

let logoutStr =
    Logout
    |> toFormattedCommandWithDefaults
// FormattedCommand "pre|Logout|post"

答案 1 :(得分:3)

you do it like this:

let formatCommand (command:Command) =
    let sendString =
        match command with
        | Login data -> 
            // use data.CommandString and data.Parameters to format your result
        | Logout data -> // dito
    { Command = command; SendString = sendString }

by the way:

  • you wrote that your Logout should have no parameters, yet you use CommandData too
  • Command and FormattedCommand share quite a lot - maybe you should use a ADT here too

答案 2 :(得分:2)

let formatCommand (command:Command) =
    { Command = command; SendString = match command with
                                      | Login c -> c.CommandString
                                      | Logout c -> c.CommandString }