F#线程通过展开更改状态 [英] F# Threading Changing State Through Unfold

查看:112
本文介绍了F#线程通过展开更改状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试处理一系列项目,其中处理步骤依赖于先前项目的某些附加累积状态(排序并不重要).

I'm trying to process a sequence of items whereby the process step relies on some additional cumulative state from the prior items (ordering isn't important).

本质上:

  1. 我有一个Seq<'A>
  2. 我有一个(Type * int) list被称为skip list
  3. 我有一个处理步骤'A -> (Type * int) list -> 'B option
    • 这将获取当前的跳过列表
  1. I have a Seq<'A>
  2. I have a (Type * int) list referred to as the skip list
  3. I have a process step 'A -> (Type * int) list -> 'B option
    • This takes the current skip list

该方法本质上是:

Seq<'A'> -> (Type * int) list -> (Type * int) list

因此,我们采用一堆输入项和一个初始跳过列表,并生成一个最终跳过列表.

So we take a bunch of input items and an initial skip list and produce a final skip list.

到目前为止,我基本上已经掌握了以下内容:

I've basically got the following so far:

sourceItems
|> Seq.map (fun srcItem -> (srcItem, outerSkip))
|> Seq.unfold (fun elem ->
    match elem with
    | SeqEmpty -> None
    | SeqCons((srcItem, skip), tail) -> 
        match process(srcItem, skip) with
        | Some targetItem -> Some((Some targetItem, skip), tail)
        | None -> Some((None, skip), tail |> Seq.map (fun (i, skp) -> (i, (srcItem.GetType(), liD srcItem) :: skp))))

SeqEmptySeqCons为活动模式:

let (|SeqEmpty|SeqCons|) (xs: 'a seq) =
    if Seq.isEmpty xs then SeqEmpty
    else SeqCons(Seq.head xs, Seq.skip 1 xs)

到目前为止,我的过程基本上只是从项目开始,然后向每个项目添加初始跳过,展开并映射剩余的seq以具有相同的项目,但是具有新的跳过列表.

My process so far basically just starts off with the items and adds the initial skip to each, unfolds and maps the remaining seq to have the same item but with the new skip list.

我对此有很多问题:

  1. 丑陋而令人困惑的地狱
  2. 我敢肯定它不如表现

理想情况下,我想避免需要映射项目以首先包括初始跳过列表的方法,但是除了将其映射为仅包含对象之外,我不确定如何将其付诸实践.序列中的第一个元素.

Ideally I'd like to avoid the need to map the items to include the initial skip list in the first place, but then I'm not sure how I'd get that into the unfold aside from mapping it into just the first element in the sequence.

基于采用中间状态的列表处理(马克的答案)

我已经可以使用:

items
|> Seq.fold (fun (skip) srcItem ->
    match process(srcItem, skip) with
    | None -> (srcItem.GetType(), liD srcItem) :: skip
    | Some tgtItem ->
        skip
    ) outerSkip

除了有物品时所需的所有东西以外,似乎实际上可以解决问题!

Which aside from all the stuff needed when there is an item, appears to actually do the trick!

与展开方法相比,此操作明显简单,但是我不清楚它的工作方式.

This is significantly simpler than the unfold approach, but I'm a little unclear on exactly how it's working.

我假设fun (skip) srcItem -> ...本质上是在创建一个期望附加参数的函数,该函数可以通过某些事物的魔力(部分应用程序)来使用outerSkip提供给fold-是这样吗?

I'm assuming that fun (skip) srcItem -> ... is essentially creating a function expecting an additional parameter that through the magic of something (partial application?) I'm able to provide to fold using outerSkip - is this right?

推荐答案

我最终采用了问题中提到的折叠策略.

I ended up adopting the fold strategy as mentioned in the question.

最终代码是:

let result =
    items
    |> Seq.fold (fun (skip, targetItems), srcItem ->
        match process(srcItem, skip) with
        | None -> ((srcItem.GetType(), getId srcItem) :: skip, targetItems)
        | Some tgtItem -> (skip, tgtItem :: targetItems)) (outerSkip, [])

result是一个元组((Type * int) list, obj list),这正是我想要的.

With result being a tuple ((Type * int) list, obj list) which is exactly what I wanted.

然后我可以对目标项目采取行动,并只返回最终的跳过列表.

I'm then able to take action on the target items, and to just return the final skip list.

与我以前使用的展开方法相比,这是巨大的改进.

This is a huge improvement over the unfold method I was using previously.

这篇关于F#线程通过展开更改状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆