FSharpPlus trySscanf 上的活动模式
Active Pattern on FSharpPlus trySscanf
我正在尝试围绕 FSharpPlus's trySscanf
创建一个活动模式 Scan
,以便以下工作:
let res = // res = 42
match "Hello 42 World" with
| Scan "Hello %i World" n -> n
我理解不完整的活动模式的工作方式,我只需要 return 一个选项,trySscanf
已经 return 一个选项,所以我尝试了以下操作:
let (|Scan|_|) = trySscanf
当这不起作用时,我尝试了更明确的
let (|Scan|_|) pattern input = trySscanf pattern input
它们都因以下编译错误而失败:
Type constraint mismatch when applying the default type 'obj' for a type inference variable. No overloads match for method 'TryParseArray'.
Known return type: (string [] -> obj option)
Known type parameters: < obj , Internals.TryParseArray >
Available overloads:
- static member Internals.TryParseArray.TryParseArray : ^t * obj -> (string [] -> ^t option) when (Control.TryParse or ^t) : (static member TryParse : ^t * Control.TryParse -> (string -> ^t option)) // Argument at index 1 doesn't match
- static member Internals.TryParseArray.TryParseArray : ('t1 * 't2' * 't3 * 't4 * 't5 * 't6 * 't7) * Internals.TryParseArray -> (string [] -> ( ^a7 * ^a8 * ^a9 * ^a10 * ^a11 * ^a12 * ^a13) option) when (Control.TryParse or ^a7) : (static member TryParse : ^a7 * Control.TryParse -> (string -> ^a7 option)) and (Control.TryParse or ^a8) : (static member TryParse : ^a8 * Control.TryParse -> (string -> ^a8 option)) and (Control.TryParse or ^a9) : (static member TryParse : ^a9 * Control.TryParse -> (string -> ^a9 option)) and (Control.TryParse or ^a10) : (static member TryParse : ^a10 * Control.TryParse -> (string -> ^a10 option)) and (Control.TryParse or ^a11) : (static member TryParse : ^a11 * Control.TryParse -> (string -> ^a11 option)) and (Control.TryParse or ^a12) : (static member TryParse : ^a12 * Control.TryParse -> (string -> ^a12 option)) and (Control.TryParse or ^a13) : (static member TryParse : ^a13 * Control.TryParse -> (string -> ^a13 option)) // Argument at index 1 doesn't match
- static member Internals.TryParseArray.TryParseArray : ('t1 * 't2' * 't3 * 't4 * 't5 * 't6) * Internals.TryParseArray -> (string [] -> ( ^a6 * ^a7 * ^a8 * ^a9 * ^a10 * ^a11) option) when (Control.TryParse or ^a6) : (static member TryParse : ^a6 * Control.TryParse -> (string -> ^a6 option)) and (Control.TryParse or ^a7) : (static member TryParse : ^a7 * Control.TryParse -> (string -> ^a7 option)) and (Control.TryParse or ^a8) : (static member TryParse : ^a8 * Control.TryParse -> (string -> ^a8 option)) and (Control.TryParse or ^a9) : (static member TryParse : ^a9 * Control.TryParse -> (string -> ^a9 option)) and (Control.TryParse or ^a10) : (static member TryParse : ^a10 * Control.TryParse -> (string -> ^a10 option)) and (Control.TryParse or ^a11) : (static member TryParse : ^a11 * Control.TryParse -> (string -> ^a11 option)) // Argument at index 1 doesn't match
- static member Internals.TryParseArray.TryParseArray : ('t1 * 't2' * 't3 * 't4 * 't5) * Internals.TryParseArray -> (string [] -> ( ^a5 * ^a6 * ^a7 * ^a8 * ^a9) option) when (Control.TryParse or ^a5) : (static member TryParse : ^a5 * Control.TryParse -> (string -> ^a5 option)) and (Control.TryParse or ^a6) : (static member TryParse : ^a6 * Control.TryParse -> (string -> ^a6 option)) and (Control.TryParse or ^a7) : (static member TryParse : ^a7 * Control.TryParse -> (string -> ^a7 option)) and (Control.TryParse or ^a8) : (static member TryParse : ^a8 * Control.TryParse -> (string -> ^a8 option)) and (Control.TryParse or ^a9) : (static member TryParse : ^a9 * Control.TryParse -> (string -> ^a9 option)) // Argument at index 1 doesn't match
- static member Internals.TryParseArray.TryParseArray : ('t1 * 't2' * 't3 * 't4) * Internals.TryParseArray -> (string [] -> ( ^a4 * ^a5 * ^a6 * ^a7) option) when (Control.TryParse or ^a4) : (static member TryParse : ^a4 * Control.TryParse -> (string -> ^a4 option)) and (Control.TryParse or ^a5) : (static member TryParse : ^a5 * Control.TryParse -> (string -> ^a5 option)) and (Control.TryParse or ^a6) : (static member TryParse : ^a6 * Control.TryParse -> (string -> ^a6 option)) and (Control.TryParse or ^a7) : (static member TryParse : ^a7 * Control.TryParse -> (string -> ^a7 option)) // Argument at index 1 doesn't match
- static member Internals.TryParseArray.TryParseArray : ('t1 * 't2' * 't3) * Internals.TryParseArray -> (string [] -> ( ^a3 * ^a4 * ^a5) option) when (Control.TryParse or ^a3) : (static member TryParse : ^a3 * Control.TryParse -> (string -> ^a3 option)) and (Control.TryParse or ^a4) : (static member TryParse : ^a4 * Control.TryParse -> (string -> ^a4 option)) and (Control.TryParse or ^a5) : (static member TryParse : ^a5 * Control.TryParse -> (string -> ^a5 option)) // Argument at index 1 doesn't match
- static member Internals.TryParseArray.TryParseArray : ('t1 * 't2) * Internals.TryParseArray -> (string [] -> ( ^a2 * ^a3) option) when (Control.TryParse or ^a2) : (static member TryParse : ^a2 * Control.TryParse -> (string -> ^a2 option)) and (Control.TryParse or ^a3) : (static member TryParse : ^a3 * Control.TryParse -> (string -> ^a3 option)) // Argument at index 1 doesn't match
- static member Internals.TryParseArray.TryParseArray : Internals.Id<'t1> * Internals.TryParseArray -> (string [] -> Internals.Id< ^a1> option) when (Control.TryParse or ^a1) : (static member TryParse : ^a1 * Control.TryParse -> (string -> ^a1 option)) // Argument at index 1 doesn't match
- static member Internals.TryParseArray.TryParseArray : Tuple< ^t1> * Internals.TryParseArray -> (string [] -> Tuple< ^t1> option) when (Control.TryParse or ^t1) : (static member TryParse : ^t1 * Control.TryParse -> (string -> ^t1 option)) // Argument at index 1 doesn't match
- static member Internals.TryParseArray.TryParseArray : t: ^t * Internals.TryParseArray -> (string [] -> ^t option) when ^t : (member get_Item1 : ^t -> ^t1) and ^t : (member get_Item2 : ^t -> ^t2) and ^t : (member get_Item3 : ^t -> ^t3) and ^t : (member get_Item4 : ^t -> ^t4) and ^t : (member get_Item5 : ^t -> ^t5) and ^t : (member get_Item6 : ^t -> ^t6) and ^t : (member get_Item7 : ^t -> ^t7) and ^t : (member get_Rest : ^t -> ^tr) and (Control.TryParse or ^t1) : (static member TryParse : ^t1 * Control.TryParse -> (string -> ^t1 option)) and (Control.TryParse or ^t2) : (static member TryParse : ^t2 * Control.TryParse -> (string -> ^t2 option)) and (Control.TryParse or ^t3) : (static member TryParse : ^t3 * Control.TryParse -> (string -> ^t3 option)) and (Control.TryParse or ^t4) : (static member TryParse : ^t4 * Control.TryParse -> (string -> ^t4 option)) and (Control.TryParse or ^t5) : (static member TryParse : ^t5 * Control.TryParse -> (string -> ^t5 option)) and (Control.TryParse or ^t6) : (static member TryParse : ^t6 * Control.TryParse -> (string -> ^t6 option)) and (Control.TryParse or ^t7) : (static member TryParse : ^t7 * Control.TryParse -> (string -> ^t7 option)) and (Internals.TryParseArray or ^tr) : (static member TryParseArray : ^tr * Internals.TryParseArray -> (string [] -> ^tr option)) // Argument 't' doesn't match
- static member Internals.TryParseArray.TryParseArray : unit * Internals.TryParseArray -> (string [] -> unit) // Argument at index 1 doesn't match Consider adding further type constraintsF# Compiler(71)
很明显,trySscanf 有一堆我没有考虑的重载,而且我不确定该怎么做。
我正在尝试做的事情是否可行?
有趣的是,如果我添加 match
表达式,编译错误就会消失,但是我可能只使用我尝试的第一个匹配案例的 PrintfFormat
:
let parseLine line =
match line with
| Scan "mem[%i] = %i" (address, value) -> Op address value
| Scan "mask = %s" str -> Mask str
最后一行表示错误:
This expression was expected to have type
'int * int'
but here has type
'string' (F# Compiler(1))
您只是忘记了声明您的函数 inline
,这样做它就可以正常工作了:
#r "nuget: FSharpPlus"
open FSharpPlus
let inline (|Scan|_|) pattern input = trySscanf pattern input
let res48 =
match "Hello 42 6 World" with
| Scan "Hello %i World" n -> n
| Scan "Hello %i %i World" (n1, n2) -> n1 + n2
之所以将其声明为内联是因为具有约束的函数只能声明为内联,这与您要编写一个将每种数字类型的数字输入加倍的函数相同。
我正在尝试围绕 FSharpPlus's trySscanf
创建一个活动模式 Scan
,以便以下工作:
let res = // res = 42
match "Hello 42 World" with
| Scan "Hello %i World" n -> n
我理解不完整的活动模式的工作方式,我只需要 return 一个选项,trySscanf
已经 return 一个选项,所以我尝试了以下操作:
let (|Scan|_|) = trySscanf
当这不起作用时,我尝试了更明确的
let (|Scan|_|) pattern input = trySscanf pattern input
它们都因以下编译错误而失败:
Type constraint mismatch when applying the default type 'obj' for a type inference variable. No overloads match for method 'TryParseArray'.
Known return type: (string [] -> obj option)
Known type parameters: < obj , Internals.TryParseArray >
Available overloads:
- static member Internals.TryParseArray.TryParseArray : ^t * obj -> (string [] -> ^t option) when (Control.TryParse or ^t) : (static member TryParse : ^t * Control.TryParse -> (string -> ^t option)) // Argument at index 1 doesn't match
- static member Internals.TryParseArray.TryParseArray : ('t1 * 't2' * 't3 * 't4 * 't5 * 't6 * 't7) * Internals.TryParseArray -> (string [] -> ( ^a7 * ^a8 * ^a9 * ^a10 * ^a11 * ^a12 * ^a13) option) when (Control.TryParse or ^a7) : (static member TryParse : ^a7 * Control.TryParse -> (string -> ^a7 option)) and (Control.TryParse or ^a8) : (static member TryParse : ^a8 * Control.TryParse -> (string -> ^a8 option)) and (Control.TryParse or ^a9) : (static member TryParse : ^a9 * Control.TryParse -> (string -> ^a9 option)) and (Control.TryParse or ^a10) : (static member TryParse : ^a10 * Control.TryParse -> (string -> ^a10 option)) and (Control.TryParse or ^a11) : (static member TryParse : ^a11 * Control.TryParse -> (string -> ^a11 option)) and (Control.TryParse or ^a12) : (static member TryParse : ^a12 * Control.TryParse -> (string -> ^a12 option)) and (Control.TryParse or ^a13) : (static member TryParse : ^a13 * Control.TryParse -> (string -> ^a13 option)) // Argument at index 1 doesn't match
- static member Internals.TryParseArray.TryParseArray : ('t1 * 't2' * 't3 * 't4 * 't5 * 't6) * Internals.TryParseArray -> (string [] -> ( ^a6 * ^a7 * ^a8 * ^a9 * ^a10 * ^a11) option) when (Control.TryParse or ^a6) : (static member TryParse : ^a6 * Control.TryParse -> (string -> ^a6 option)) and (Control.TryParse or ^a7) : (static member TryParse : ^a7 * Control.TryParse -> (string -> ^a7 option)) and (Control.TryParse or ^a8) : (static member TryParse : ^a8 * Control.TryParse -> (string -> ^a8 option)) and (Control.TryParse or ^a9) : (static member TryParse : ^a9 * Control.TryParse -> (string -> ^a9 option)) and (Control.TryParse or ^a10) : (static member TryParse : ^a10 * Control.TryParse -> (string -> ^a10 option)) and (Control.TryParse or ^a11) : (static member TryParse : ^a11 * Control.TryParse -> (string -> ^a11 option)) // Argument at index 1 doesn't match
- static member Internals.TryParseArray.TryParseArray : ('t1 * 't2' * 't3 * 't4 * 't5) * Internals.TryParseArray -> (string [] -> ( ^a5 * ^a6 * ^a7 * ^a8 * ^a9) option) when (Control.TryParse or ^a5) : (static member TryParse : ^a5 * Control.TryParse -> (string -> ^a5 option)) and (Control.TryParse or ^a6) : (static member TryParse : ^a6 * Control.TryParse -> (string -> ^a6 option)) and (Control.TryParse or ^a7) : (static member TryParse : ^a7 * Control.TryParse -> (string -> ^a7 option)) and (Control.TryParse or ^a8) : (static member TryParse : ^a8 * Control.TryParse -> (string -> ^a8 option)) and (Control.TryParse or ^a9) : (static member TryParse : ^a9 * Control.TryParse -> (string -> ^a9 option)) // Argument at index 1 doesn't match
- static member Internals.TryParseArray.TryParseArray : ('t1 * 't2' * 't3 * 't4) * Internals.TryParseArray -> (string [] -> ( ^a4 * ^a5 * ^a6 * ^a7) option) when (Control.TryParse or ^a4) : (static member TryParse : ^a4 * Control.TryParse -> (string -> ^a4 option)) and (Control.TryParse or ^a5) : (static member TryParse : ^a5 * Control.TryParse -> (string -> ^a5 option)) and (Control.TryParse or ^a6) : (static member TryParse : ^a6 * Control.TryParse -> (string -> ^a6 option)) and (Control.TryParse or ^a7) : (static member TryParse : ^a7 * Control.TryParse -> (string -> ^a7 option)) // Argument at index 1 doesn't match
- static member Internals.TryParseArray.TryParseArray : ('t1 * 't2' * 't3) * Internals.TryParseArray -> (string [] -> ( ^a3 * ^a4 * ^a5) option) when (Control.TryParse or ^a3) : (static member TryParse : ^a3 * Control.TryParse -> (string -> ^a3 option)) and (Control.TryParse or ^a4) : (static member TryParse : ^a4 * Control.TryParse -> (string -> ^a4 option)) and (Control.TryParse or ^a5) : (static member TryParse : ^a5 * Control.TryParse -> (string -> ^a5 option)) // Argument at index 1 doesn't match
- static member Internals.TryParseArray.TryParseArray : ('t1 * 't2) * Internals.TryParseArray -> (string [] -> ( ^a2 * ^a3) option) when (Control.TryParse or ^a2) : (static member TryParse : ^a2 * Control.TryParse -> (string -> ^a2 option)) and (Control.TryParse or ^a3) : (static member TryParse : ^a3 * Control.TryParse -> (string -> ^a3 option)) // Argument at index 1 doesn't match
- static member Internals.TryParseArray.TryParseArray : Internals.Id<'t1> * Internals.TryParseArray -> (string [] -> Internals.Id< ^a1> option) when (Control.TryParse or ^a1) : (static member TryParse : ^a1 * Control.TryParse -> (string -> ^a1 option)) // Argument at index 1 doesn't match
- static member Internals.TryParseArray.TryParseArray : Tuple< ^t1> * Internals.TryParseArray -> (string [] -> Tuple< ^t1> option) when (Control.TryParse or ^t1) : (static member TryParse : ^t1 * Control.TryParse -> (string -> ^t1 option)) // Argument at index 1 doesn't match
- static member Internals.TryParseArray.TryParseArray : t: ^t * Internals.TryParseArray -> (string [] -> ^t option) when ^t : (member get_Item1 : ^t -> ^t1) and ^t : (member get_Item2 : ^t -> ^t2) and ^t : (member get_Item3 : ^t -> ^t3) and ^t : (member get_Item4 : ^t -> ^t4) and ^t : (member get_Item5 : ^t -> ^t5) and ^t : (member get_Item6 : ^t -> ^t6) and ^t : (member get_Item7 : ^t -> ^t7) and ^t : (member get_Rest : ^t -> ^tr) and (Control.TryParse or ^t1) : (static member TryParse : ^t1 * Control.TryParse -> (string -> ^t1 option)) and (Control.TryParse or ^t2) : (static member TryParse : ^t2 * Control.TryParse -> (string -> ^t2 option)) and (Control.TryParse or ^t3) : (static member TryParse : ^t3 * Control.TryParse -> (string -> ^t3 option)) and (Control.TryParse or ^t4) : (static member TryParse : ^t4 * Control.TryParse -> (string -> ^t4 option)) and (Control.TryParse or ^t5) : (static member TryParse : ^t5 * Control.TryParse -> (string -> ^t5 option)) and (Control.TryParse or ^t6) : (static member TryParse : ^t6 * Control.TryParse -> (string -> ^t6 option)) and (Control.TryParse or ^t7) : (static member TryParse : ^t7 * Control.TryParse -> (string -> ^t7 option)) and (Internals.TryParseArray or ^tr) : (static member TryParseArray : ^tr * Internals.TryParseArray -> (string [] -> ^tr option)) // Argument 't' doesn't match
- static member Internals.TryParseArray.TryParseArray : unit * Internals.TryParseArray -> (string [] -> unit) // Argument at index 1 doesn't match Consider adding further type constraintsF# Compiler(71)
很明显,trySscanf 有一堆我没有考虑的重载,而且我不确定该怎么做。
我正在尝试做的事情是否可行?
有趣的是,如果我添加 match
表达式,编译错误就会消失,但是我可能只使用我尝试的第一个匹配案例的 PrintfFormat
:
let parseLine line =
match line with
| Scan "mem[%i] = %i" (address, value) -> Op address value
| Scan "mask = %s" str -> Mask str
最后一行表示错误:
This expression was expected to have type
'int * int'
but here has type
'string' (F# Compiler(1))
您只是忘记了声明您的函数 inline
,这样做它就可以正常工作了:
#r "nuget: FSharpPlus"
open FSharpPlus
let inline (|Scan|_|) pattern input = trySscanf pattern input
let res48 =
match "Hello 42 6 World" with
| Scan "Hello %i World" n -> n
| Scan "Hello %i %i World" (n1, n2) -> n1 + n2
之所以将其声明为内联是因为具有约束的函数只能声明为内联,这与您要编写一个将每种数字类型的数字输入加倍的函数相同。