Активный шаблон на FSharpPlus trySscanf

Я пытаюсь создать активный шаблон Scan вокруг trySscanf FSharpPlus, чтобы работало следующее:

let res = // res = 42
  match "Hello 42 World" with
  | Scan "Hello %i World" n -> n

Как я понимаю, неполные активные шаблоны работают, мне просто нужно вернуть опцию, trySscanf уже возвращает опцию, поэтому я попробовал следующее:

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))
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
62
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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

Причина, по которой вы объявили его встроенным, заключается в том, что функции с ограничениями могут быть объявлены только встроенными, это тот же случай, когда вы хотите написать функцию, которая удваивает числовой ввод для каждого числового типа.

Другие вопросы по теме