Ограничения члена F # + ^ a byref параметры

После того, как вы немного поиграете с функцией ограничения членства в F # и функцией записи, вот так:

let inline parse< ^a when ^a : (static member Parse: string -> ^a) > s =
    (^a: (static member Parse: string -> ^a) s)

Это прекрасно работает.

let xs = [ "123"; "456"; "999" ] |> List.map parse<int>

Я пытаюсь написать другую функцию tryParse, которая использует статический метод TryParse и оборачивает результат анализа в тип 'a option для лучшей поддержки в F #. Что-то вроде этого не компилируется:

let inline tryParse s =
    let mutable x = Unchecked.defaultof< ^a>
    if (^a: (static member TryParse: string * ^a byref -> bool) (s, &x))
        then Some x else None

Ошибка:

  

ошибка FS0001: это выражение было   ожидается, чтобы иметь тип        byref <'a> , но здесь есть тип        'ссылка

F # ref -клетки тоже не работают:

let inline tryParse s =
    let x = ref Unchecked.defaultof< ^a>
    if (^a: (static member TryParse: string * ^a byref -> bool) (s, x))
        then Some x else None

Что я делаю не так?

7 голосов | спросил ControlFlow 11 Jpm1000000pmTue, 11 Jan 2011 14:00:37 +030011 2011, 14:00:37

3 ответа


0

UPDATE

Похоже, это исправлено в F # 3.0.

Старый ответ .

Я согласен с комментарием Стивена, что это, скорее всего, ошибка. Есть много ограничений на типы byref, поэтому для меня не особенно удивительно, что они плохо работают с ограничениями членов. Вот (уродливый) обходной путь, использующий отражение:

type parseDel<'a> = delegate of string * 'a byref -> bool

type Parser< ^a when ^a : (static member TryParse: string * ^a byref -> bool)> private ()=
  static let parser = System.Delegate.CreateDelegate(typeof<parseDel<'a>>, typeof<'a>.GetMethod("TryParse", [|typeof<string>; typeof<'a>.MakeByRefType()|])) :?> parseDel<'a>
  static member inline ParseDel = parser

let inline tryParse (s:string) =
  let mutable x = Unchecked.defaultof< ^a>
  if Parser<_>.ParseDel.Invoke(s, &x) then
    Some x
  else None

let one : int option = tryParse "1"
ответил kvb 11 Jpm1000000pmTue, 11 Jan 2011 17:44:28 +030011 2011, 17:44:28
0

Я думаю, что это тоже ошибка, связанная с ограничениями членов и типами byref. Я могу сделать немного менее уродливую версию отражения, изменив сигнатуру ограничения члена:

let inline tryParse<'a when 'a : (static member TryParse : string -> 'a byref -> bool)>  s  =
    let args = [| s ; null |]
    if typeof<'a>
        .GetMethod("TryParse", [| typeof<string>; typeof< ^a>.MakeByRefType() |])
        .Invoke(null, args) = box true 
        then Some (args.[1] :?> 'a) 
        else None

Это очень близко:

let inline tryParse< ^a when ^a: (static member TryParse: string -> ^a byref -> bool)> s =
    let mutable x = Unchecked.defaultof<'a>
    if (^a: (static member TryParse: string -> ^a byref -> bool) (s, &x))
        then Some x else None

но я получаю сообщение об ошибке FS0421: адрес переменной 'x' нельзя использовать в этот момент , когда я пытаюсь скомпилировать его.

ответил Huusom 12 Jpm1000000pmWed, 12 Jan 2011 17:17:28 +030011 2011, 17:17:28
0

Это компилируется, но все равно не работает должным образом:

let inline tryParse< ^a when ^a: (static member TryParse: string -> ^a ref -> bool) > s =
  let x = ref Unchecked.defaultof< ^a>
  match (^a: (static member TryParse: string -> ^a ref -> bool )  (s, x)) with
    | false -> None
    | true -> Some(!x)

// returns [Some 0; Some 0; Some 0; null], so our tryParse is not retrieving the value from the ref
let xs = [ "1"; "456"; "999"; "a" ] |> List.map tryParse<int>

в данном конкретном случае, вместо использования отражения, я просто воссоздаю TryParse из Parse в f #

let inline tryParse< ^a when ^a: (static member Parse: string -> ^a) > s =
  try  
    Some(^a: (static member Parse: string -> ^a)  s)
  with
    | exn -> None

let xs = [ "1"; "456"; "999"; "a" ] |> List.map tryParse<int>
ответил Paolo Falabella 5 FebruaryEurope/MoscowbSat, 05 Feb 2011 11:53:43 +0300000000amSat, 05 Feb 2011 11:53:43 +030011 2011, 11:53:43

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132