在F#中,如何基于解析的有效负载对类型进行水合物化?
我来自命令式编程背景,在理解如何实现(应该是什么)一个相对简单的编程任务时遇到问题 假设我有一个F型: 我希望基于分隔的负载创建并创建此类型的实例:在F#中,如何基于解析的有效负载对类型进行水合物化?,f#,F#,我来自命令式编程背景,在理解如何实现(应该是什么)一个相对简单的编程任务时遇到问题 假设我有一个F型: 我希望基于分隔的负载创建并创建此类型的实例: DE=MyDescription;AC=0 其中AC为0表示false,1表示true 我编写了两个函数来执行解析: let RecordParser (record:string) = record.Split([|';'|], StringSplitOptions.RemoveEmptyEntries) let Attribute
DE=MyDescription;AC=0
其中AC为0表示false
,1表示true
我编写了两个函数来执行解析:
let RecordParser (record:string) =
record.Split([|';'|], StringSplitOptions.RemoveEmptyEntries)
let AttributeParser (kvp:string) =
kvp.Split [|'='|]
解析分隔的有效负载以返回MyType的新实例(该实例由解析的Description
和Active
值组成)的函数的实现是什么样的
我尝试了一种使用Array.iter
的路由,但是当match
ing键时,我似乎无法将其编译。我已经做到了:
let Hydrater payload
let kvps = RecordParser payload
kvps |> Array.iter(fun (x) ->
// How to match on the keys of "DE" and "AC" to extract the value and construct MyType
()
)
让我们假设
MyType
被定义为:
您所描述的内容可以看作是要覆盖在默认值之上的值的累积:
let hydrate payload =
let kvps = RecordParser payload
let startingValue = { Description = ""; Active = false }
kvps
|> Seq.fold
(fun state kvp ->
match kvp with
| [| 'Description'; '='; description |] -> { state with Description = description }
| [| 'AC'; '='; '0' |] -> { state with Active = false }
| [| 'AC'; '='; '1' |] -> { state with Active = true }
| _ -> failwith "Not implemented") startingValue
这里的startingValue
是“默认”值。获取起始值
,并将其用作状态
的初始值。每次对函数求值后,返回值将作为状态
传递给函数的下一次调用。通常,可以使用Seq.fold
替换C#中某些类型的foreach
循环
这个F#:
大致相当于这个C#:
在本例中,您将执行与C#中相同的操作(因为它只在运行时才知道):检查您是否有足够的记录,检查每个记录是否有足够的部分,然后使用数组索引(
[i]
)和您常用的布尔和比较函数来提醒我速度有点慢,但你能解释一下Seq.fold是如何获得起始价值的吗?它是以某种方式隐式传递的吗?@thehowler我最新的编辑wrt Seq.fold有意义吗?是的。我错过了“state”值的隐式类型。
type MyType = {
Description : string
Active : bool
}
let hydrate payload =
let kvps = RecordParser payload
let startingValue = { Description = ""; Active = false }
kvps
|> Seq.fold
(fun state kvp ->
match kvp with
| [| 'Description'; '='; description |] -> { state with Description = description }
| [| 'AC'; '='; '0' |] -> { state with Active = false }
| [| 'AC'; '='; '1' |] -> { state with Active = true }
| _ -> failwith "Not implemented") startingValue
Seq.fold (fun state curr -> doSomething state curr) startingValue items
var state = startingValue;
foreach(var curr in items)
{
state = doSomething(state, curr);
}