F # Inline Функция Специализация - PullRequest
2 голосов
/ 21 декабря 2010

Мой текущий проект включает в себя лексический и синтаксический анализ кода скрипта, и поэтому я использую fslex и fsyacc. Fslex LexBuffers могут быть в вариантах LexBuffer<char> и LexBuffer<byte>, и я хотел бы иметь возможность использовать оба.

Для того, чтобы использовать оба, мне нужна функция лексемы типа ^ buf -> string. До сих пор мои попытки специализации выглядели так:

let inline lexeme (lexbuf: ^buf) : ^buf -> string where ^buf : (member Lexeme: char array) =
  new System.String(lexbuf.Lexeme)

let inline lexeme (lexbuf: ^buf) : ^buf -> string where ^buf : (member Lexeme: byte array) =
  System.Text.Encoding.UTF8.GetString(lexbuf.Lexeme)

Я получаю ошибку типа, утверждающую, что тело функции должно иметь тип ^buf -> string, но выводимый тип - просто string. Понятно, что я делаю что-то (в основном?) Неправильно.

Возможно ли то, что я пытаюсь сделать в F #? Если так, может ли кто-нибудь указать мне правильный путь?

Спасибо!

Ответы [ 3 ]

2 голосов
/ 21 декабря 2010

Функции и элементы, помеченные как inline, не могут быть перегружены, поэтому ваша исходная стратегия не будет работать. Вам нужно написать разные коды для обоих объявлений, поэтому вам нужно использовать перегрузку (если вы хотите написать это без бокса и динамических тестов типов).

Если вы используете стандартные инструменты F #, то тип, который вы получите в качестве буфера, всегда будет LexBuffer<'T>, и вы захотите иметь две перегрузки на основе аргумента типа. В этом случае вам вообще не нужны статические ограничения членов, и вы можете написать просто:

type Utils = 
  static member lexeme(buf:LexBuffer<char>) = 
    new System.String(buf.Lexeme)
  static member lexeme(buf:LexBuffer<byte>) = 
    System.Text.Encoding.UTF8.GetString(buf.Lexeme)
0 голосов
/ 21 декабря 2010
type LexBuffer<'a>(data : 'a []) =
  member this.Lexeme = data

let lexeme (buf : LexBuffer<'a>) =
  match box buf.Lexeme with
  | :? (char array) as chArr ->
      new System.String(chArr)
  | :? (byte array) as byArr ->
      System.Text.Encoding.UTF8.GetString(byArr)
  | _ -> invalidArg "buf" "must be either char or byte LexBuffer"

new LexBuffer<byte>([| 97uy; 98uy; 99uy |])
|> lexeme
|> printfn "%A"

new LexBuffer<char>([| 'a'; 'b'; 'c' |])
|> lexeme
|> printfn "%A"
0 голосов
/ 21 декабря 2010

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

...