我在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 = ?? }
答案 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:
Logout
should have no parameters, yet you use CommandData
tooCommand
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 }