Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List F#活动模式列表.过滤器或同等产品_List_F#_Active Pattern - Fatal编程技术网

List F#活动模式列表.过滤器或同等产品

List F#活动模式列表.过滤器或同等产品,list,f#,active-pattern,List,F#,Active Pattern,我有各种类型的记录 type tradeLeg = { id : int ; tradeId : int ; legActivity : LegActivityType ; actedOn : DateTime ; estimates : legComponents ; entryType : ShareOrDollarBased ; confirmedPrice: DollarsPerShare option; actuals :

我有各种类型的记录

type tradeLeg = {
    id : int ;
    tradeId : int ;
    legActivity : LegActivityType ;
    actedOn : DateTime ;
    estimates : legComponents ;
    entryType : ShareOrDollarBased ;
    confirmedPrice: DollarsPerShare option;
    actuals : legComponents option ; 


type trade = {
    id : int ;
    securityId : int ;
    ricCode : string ;
    tradeActivity : TradeType ;
    enteredOn : DateTime ;
    closedOn : DateTime ;
    tradeLegs : tradeLeg list  ;
}
显然,交易腿是交易的一种类型。一个交易段可以是已结算或未结算(或未结算但价格已确认)-因此我定义了活动模式:

let (|LegIsSettled|LegIsConfirmed|LegIsUnsettled|) (l: tradeLeg) = 
        if Helper.exists l.actuals then LegIsSettled
        elif Helper.exists l.confirmedPrice then LegIsConfirmed
        else LegIsUnsettled
然后确定交易是否已结算(基于与合法结算模式匹配的所有分支):

let (|TradeIsSettled|TradeIsUnsettled|) (t: trade) = 
        if List.exists (
            fun l -> 
                match l with 
                    | LegIsSettled -> false 
                    | _ -> true) t.tradeLegs then TradeIsSettled
        else TradeIsUnsettled
我可以看到使用活动模式的一些优点,但是我认为有一种更有效的方法可以查看列表中的任何项是否匹配(或不匹配)活动模式,而无需专门为其编写lambda表达式,并使用list.exist

问题有两个方面:

  • 有没有更简洁的方式来表达这一点
  • 有没有办法抽象功能/表达式

    (fun l -> 
          match l with 
          | LegIsSettled -> false 
          | _ -> true)
    
  • 以致

    let itemMatchesPattern pattern item  =
        match item with
             | pattern -> true
             | _ -> false
    
    我可以这样写(因为我正在重用这个设计模式):


    想法?

    要回答您关于活动模式的问题,让我用一个更简单的例子:

    let (|Odd|Even|) n = 
      if n % 2 = 0 then Even else Odd
    
    当您使用
    (|奇|偶|)
    声明具有多个选项的模式时,编译器将其理解为返回类型为
    Choice
    的值的函数。因此,您可以使用的活动模式是整个组合
    |奇|偶
    ,而不仅仅是两个可以独立使用的结构(例如
    |奇数|
    |偶数|

    可以将活动模式视为第一类函数,但如果您使用具有多个选项的模式,则无法使用它:

    设模式=(|奇|偶|);; val模式:int->Choice

    您可以编写测试值是否与指定模式匹配的函数,但您需要很多函数(因为有许多
    Choice
    类型因类型参数的数量而重载):

    像这样的东西在你的情况下会起作用,但它远不是完美的

    如果您声明了多个部分活动模式,您可以做得更好一些(但是您当然失去了完全活动模式的一些好的方面,例如完整性检查):

    现在,您可以编写一个函数来检查值是否与模式匹配:

    let matches pattern value = 
      match pattern value with
      | Some _ -> true
      | None -> false
    
    > matches (|Odd|_|) 1;;
    val it : bool = true
    > matches (|Even|_|) 2;;
    val it : bool = true
    

    <强>摘要<强>虽然可能有一些或多或少优雅的方式来实现您所需要的,但我可能会考虑活动模式是否比使用标准函数具有更大的优势。最好先使用函数来初始化代码,然后决定哪些结构可以作为活动模式使用。然后添加活动模式。在这种情况下,通常的代码看起来不会更糟:

    type LegResult = LegIsSettled | LegIsConfirmed | LegIsUnsettled
    
    let getLegStatus (l: tradeLeg) =    
        if Helper.exists l.actuals then LegIsSettled   
        elif Helper.exists l.confirmedPrice then LegIsConfirmed   
        else LegIsUnsettled
    
    // Later in the code you would use pattern matching
    match getLegStatus trade with
    | LegIsSettled -> // ...
    | LegIsUnSettled -> // ...
    
    // But you can still use higher-order functions too
    trades |> List.exist (fun t -> getLegStatus t = LegIsSettled)
    
    // Which can be rewritten (if you like point-free style):
    trades |> List.exist (getLegStatus >> ((=) LegIsSettled))
    
    // Or you can write helper function (which is more readable):
    let legStatusIs check trade = getLegStatus trade = check
    trades |> List.exist (legStatusIs LegIsSettled)
    

    除了Tomas关于活动模式的实际细节的观点外,请注意,您可以将
    fun x->match x with |…
    缩短为
    function |…
    ,这样可以节省一些击键次数,同时还可以避免编写可能毫无意义的标识符。

    +1:酷!我不知道您可以通过
    (|奇| | | |
    作为一个函数的值:)当我发现这是可能的时候,我也很惊讶。实际上,活动模式有点像操作符。使用操作符你可以声明
    let(++)ab=a+b
    并使用它们
    List.map(++)
    。使用活动模式:
    let(| Xyz | |)a=None
    List.map(| Xyz |)
    (名称中的空格实际上也是允许的!)谢谢你。我最初将其作为标准函数编写(尽管没有那么雄辩),并开始玩弄活动模式以释放其威力。这里有很好的信息-再次感谢你
    let (|Odd|_|) n = 
      if n % 2 = 0 then None else Some()  
    let (|Even|_|) n = 
      if n % 2 = 0 then Some() else None
    
    let matches pattern value = 
      match pattern value with
      | Some _ -> true
      | None -> false
    
    > matches (|Odd|_|) 1;;
    val it : bool = true
    > matches (|Even|_|) 2;;
    val it : bool = true
    
    type LegResult = LegIsSettled | LegIsConfirmed | LegIsUnsettled
    
    let getLegStatus (l: tradeLeg) =    
        if Helper.exists l.actuals then LegIsSettled   
        elif Helper.exists l.confirmedPrice then LegIsConfirmed   
        else LegIsUnsettled
    
    // Later in the code you would use pattern matching
    match getLegStatus trade with
    | LegIsSettled -> // ...
    | LegIsUnSettled -> // ...
    
    // But you can still use higher-order functions too
    trades |> List.exist (fun t -> getLegStatus t = LegIsSettled)
    
    // Which can be rewritten (if you like point-free style):
    trades |> List.exist (getLegStatus >> ((=) LegIsSettled))
    
    // Or you can write helper function (which is more readable):
    let legStatusIs check trade = getLegStatus trade = check
    trades |> List.exist (legStatusIs LegIsSettled)