标签: active-pattern

F#活动模式作为非静态成员

我不确定是否允许非静态公共成员活动模式,但您可以在没有编译器抱怨的情况下定义它们.如果允许它们与一个匹配的语法是什么?编译器在FooBar2.doSomething中为Foo提供了类型不匹配.期待一个'a -> Choice<'b,'c>给定的'a -> 'd -> Choice<unit,unit>

// No error in this class, static works great
type FooBar() = 
    static member (|Foo|Bar|) (x, y) =
        match x = y with
        | true -> Foo
        | false -> Bar

    member x.doSomething y =
        match x, y with
        | Foo -> ()
        | Bar -> ()

type FooBar2() = 
    member x.(|Foo|Bar|) y =
        match x = y with
        | true -> Foo
        | false -> Bar

    // compiler error …
Run Code Online (Sandbox Code Playgroud)

f# member active-pattern

4
推荐指数
1
解决办法
463
查看次数

F#活动模式List.filter或等效

我有类型的记录

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  ;
}
Run Code Online (Sandbox Code Playgroud)

贸易腿显然是一种交易类型.一条腿可能已经结算或未结算(或未结算但已确认价格) - 因此我已定义了活动模式:

let (|LegIsSettled|LegIsConfirmed|LegIsUnsettled|) (l: tradeLeg) = 
        if …
Run Code Online (Sandbox Code Playgroud)

f# list active-pattern

4
推荐指数
1
解决办法
1090
查看次数

具有活动模式的FizzBu​​zz

我正在尝试了解Active Patterns,所以我正在玩FizzBu​​zz:

let (|Fizz|_|) i = if i % 3 = 0 then Some Fizz else None
let (|Buzz|_|) i = if i % 5 = 0 then Some Buzz else None
let (|FizzBuzz|_|) i = if i % 5 = 0 && i % 3 = 0 then Some FizzBuzz else None

let findMatch = function
    | Some Fizz -> "Fizz"
    | Some Buzz -> "Buzz"
    | Some FizzBuzz -> "FizzBuzz"
    | _ -> ""

let fizzBuzz = seq …
Run Code Online (Sandbox Code Playgroud)

f# fizzbuzz active-pattern

4
推荐指数
2
解决办法
443
查看次数

按任意顺序匹配列表项目

当涉及到F#的许多领域时,我仍然是新手.我出于好奇而不是出于实际的业务需求而提出这个问题.有没有办法匹配列表中的前n个项目,无论它们出现的顺序如何?为了澄清,请考虑以下示例:

type MyEnum = 
    | Foo of int
    | Bar of float
    | Baz of string
let list = [ Foo 1 ; Bar 1.0 ; Baz "1" ]
Run Code Online (Sandbox Code Playgroud)

现在,假设我想调用some_func列表中的前两个项是a Foo和a Bar,以任何顺序.只匹配两种可能的排列很容易:

let result = 
    match list with
    | Foo n :: Bar x :: _ 
    | Bar x :: Foo n :: _ -> some_func n x
    | _ -> failwith "First 2 items must be Foo and Bar"
Run Code Online (Sandbox Code Playgroud)

但是,如果我需要调用一个函数,如果前3项是a Foo,Bar …

f# list pattern-matching active-pattern

4
推荐指数
1
解决办法
278
查看次数

多案例参数化活动模式返回错误FS0722只有返回一个结果的活动模式可以接受参数

由于我只发现了关于这个错误的日文页面,我想,让我们记录它并在这里问,因为我的日语有点生疏.

如果我有以下FSharp活动模式(简化示例):

let (|InRange|OutOfRange|) from too =
    function
    | input when input >= from && input <= too -> InRange
    | _ -> OutOfRange
Run Code Online (Sandbox Code Playgroud)

它完美编译并显示其类型:

val ( |InRange|OutOfRange| ) :
  from:'a -> too:'a -> _arg1:'a -> Choice<unit,unit> when 'a : comparison
Run Code Online (Sandbox Code Playgroud)

但是当我尝试使用它时,即如下所示,它会抛出一个错误:

let test i = match i with
             | InRange 10 20 -> "in range"
             | _ -> "out of range"
Run Code Online (Sandbox Code Playgroud)

抛出:错误FS0722:只有返回一个结果的活动模式可以接受参数

我可以通过把它变成两个单例参数化的活动模式来解决它,每个都返回None/Some(x),但我仍然想知道为什么我不被允许这样做和/或是否有我可以使用的语法我是不知道.我也想知道它为什么编译,但我不能用它?

f# compiler-errors active-pattern

4
推荐指数
1
解决办法
210
查看次数

与歧视联盟的主动模式匹配

有没有办法使用以下形式的区别联合与活动模式匹配?我找不到任何例子.

这就是我想要做的:

type c = a | b

type foo =
  | bar1
  | bar2 of c

//allowed
let (|MatchFoo1|_|) aString =
  match aString with
  | "abcd" -> Some bar1
  | _ -> None

//not allowed
let (|MatchFoo2|_|) aString =
  match aString with
  | "abcd" -> Some (bar2 of a)
  | _ -> None
Run Code Online (Sandbox Code Playgroud)

为什么"Some"不能以第二种方式使用?还有另一种方法可以达到同样的目的吗?

f# pattern-matching discriminated-union active-pattern

4
推荐指数
1
解决办法
324
查看次数

F#避免活动模式覆盖

我注意到我无法使用相同的选项创建两个活动模式,但我可以有两个类似的模式没有任何警告:

let (|A|B|C|) c =
   if (c = 'a') then A
   else if (c = 'b') then B
   else C

let (|A|B|D|) c =
   if (c = '1') then A
   else if (c = '2') then B
   else D
Run Code Online (Sandbox Code Playgroud)

所以当这种方式匹配时:

let check myvar =
  match myvar with 
    | A -> printf "match A\n"
    | n -> printf "match other %A\n" n
Run Code Online (Sandbox Code Playgroud)

有时候是这样的:

check 'x' // match other 'x'  
check 'a' // match other 'a'     !!
check '1' // match A …
Run Code Online (Sandbox Code Playgroud)

f# active-pattern

3
推荐指数
1
解决办法
119
查看次数

在F#中适当使用活动模式

我正在使用活动模式来解析csv格式的使用日志中的使用事件.下面列出了活动模式部分.解析整个文件效果很好,生成的序列充满了各种UsageEvents.

type SystemName = string
type SystemVersion = string
type MAC = string
type Category = string
type Game = string
type Setting = string
type StartupLocation = string

type UsageEvent =
    | SystemStart of DateTime * SystemVersion * SystemName * MAC
    | SystemEnd of DateTime
    | GameStart of DateTime * Category * Game * Setting * StartupLocation
    | GameEnd of DateTime * Category * Game
    | Other

let (|SystemStart|SystemEnd|GameStart|GameEnd|Other|) (input : string list) =
    match List.nth input 0 with …
Run Code Online (Sandbox Code Playgroud)

f# active-pattern

3
推荐指数
1
解决办法
309
查看次数

联盟成员的子集作为模式匹配中的"参数"

让我们为具有几种类型的二进制节点的树的类型定义,以及其他类型的节点,即

type Tree =
| BinaryNodeA of Tree * Tree
| BinaryNodeB of Tree * Tree
| [Other stuff...]
Run Code Online (Sandbox Code Playgroud)

我想使用递归函数来操纵这个树,该递归函数可以例如交换任何类型的二进制节点的子节点(通过构造新节点).让我疯狂的问题:如何匹配所有BinaryNodes,以便Node风格成为"参数",以便具有可应用于任何BinaryNode风格的通用交换,以返回该风味的交换节点?

我知道如何使用活动模式匹配所有BinaryNodes树:

let (|BinaryNode|_|) (tree : Tree) =
    match tree with
    | BinaryNodeA _ | BinaryNodeB _ -> Some(tree)
    | _ -> None
Run Code Online (Sandbox Code Playgroud)

但这还不够好,因为以下似乎无法实现:

match tree with
| [cases related to unary nodes..]
| BinaryNode a b -> BinaryNode b a
Run Code Online (Sandbox Code Playgroud)

换句话说,我还没有找到使用BinaryNode风格的方法,就像它是a和b之类的参数一样.相反,似乎我必须分别匹配每个BinaryNode风格.如果存在大量二进制节点风格,这可能具有实际意义.对于Fsyacc/Fslex生成的解析器/词法分析器,类型树是AST,它限制了重构它的选项.有任何想法吗?

f# discriminated-union active-pattern

3
推荐指数
1
解决办法
133
查看次数

为什么活动模式会以这种方式运行?

我在F# Design PatternsGene Belitski 的优秀书中找到了这段代码:

let (| `` I'm active pattern `` |) x = x + 2
let (`` I'm active pattern `` y) = 40
(*
val ( |`` I'm active pattern ``| ) : x:int -> int
val y : int = 42
*)
Run Code Online (Sandbox Code Playgroud)

作者认识到这是

"如果你记得一个值的let绑定是基于模式匹配的数据反汇编的角落情况,那么一个稍微令人难以置信的例子变得清晰,因此I'm active pattern应用于输入参数40并将结果42绑定到x."

我不明白.为什么I'm active pattern40适用于40,因为40在右侧?我直觉地猜测y = 38,而不是42,将表达式let (`` I'm active pattern `` y) = 40视为隐式函数.

谁能解释一下?

f# active-pattern

3
推荐指数
1
解决办法
104
查看次数