Function F#内联函数专门化

Function F#内联函数专门化,function,f#,inline,specialization,fslex,Function,F#,Inline,Specialization,Fslex,我当前的项目涉及分析和解析脚本代码,因此我使用fslex和fsyacc。Fslex LexBuffers可以是LexBuffer和LexBuffer两种类型,我希望可以同时使用这两种类型 为了使用这两个函数,我需要一个^buf->string类型的lexeme函数。到目前为止,我对专业化的尝试如下: let inline lexeme (lexbuf: ^buf) : ^buf -> string where ^buf : (member Lexeme: char array) = n

我当前的项目涉及分析和解析脚本代码,因此我使用fslex和fsyacc。Fslex LexBuffers可以是
LexBuffer
LexBuffer
两种类型,我希望可以同时使用这两种类型

为了使用这两个函数,我需要一个^buf->string类型的lexeme函数。到目前为止,我对专业化的尝试如下:

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#中可能实现吗?如果是这样,有人能给我指出正确的路径吗


谢谢

您确定用不同的参数类型重新定义
内联
函数的策略可以奏效吗?看起来您正试图向我重载…

键入LexBuffer无法重载标记为
inline
的函数和成员,因此您最初的策略无法工作。您需要为这两个声明编写不同的代码,因此需要使用重载(如果您希望在编写此声明时不使用装箱和动态类型测试)

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"

如果您使用的是标准的F#工具,那么作为缓冲区的类型将始终是
lexbuffer我肯定在尝试重载-编译器似乎不喜欢明显的第一次尝试重载,尽管它抱怨值“lexeme”的定义重复。乍一看,内联看起来很有希望,但我不知道如何实现它。也许这毕竟是不可能的。谢谢你,托马斯。我确信F#函数不能重载一定有原因——不管是什么原因,我无法理解。静态类就足够了!
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)