2010-12-21 22 views
2

現在のプロジェクトでは、スクリプトコードのレキシングと解析が行われています。そのため、私はfslexとfsyaccを使用しています。 Fslex LexBuffersはLexBuffer<char>LexBuffer<byte>のいずれかになります。両方を使用するオプションがあります。F#インライン関数の特殊化

両方を使用するには、^ 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#でも可能なことを試みていますか?もしそうなら、誰かが私に正しい道を向けることができますか?

ありがとうございます!

答えて

2

機能とメンバーがマーク見えます。両方の宣言に異なるコードを記述する必要があるので、オーバーロードを使用する必要があります(ボクシングと動的型テストなしでこれを記述したい場合)。

標準のF#ツールを使用している場合は、バッファとして取得するタイプは常にLexBuffer<'T>になり、タイプ引数に基づいて2つのオーバーロードが必要になります。このケースでは、すべての静的メンバの制約を必要としないし、ちょうど書くことができます:私は確かにオーバーロードしようとしています

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

ありがとう、トマス。私は、F#関数が過負荷にならない理由がなければならないと確信しています。何があっても、私は理解できません。静的なクラスで十分です! – Ben

0

異なる引数タイプの関数inlineを再定義するこの戦略は有効ですか?あなたが私にオーバーロードしようとしているように元の戦略が機能しませんのでinlineは、過負荷にすることができないよう...

+0

- コンパイラはしかし、過負荷にで明白な最初の刺しが好きとは思われません、値「語彙素」の重複した定義について不平を言う。インライン展開は最初の紅潮で有望に見えましたが、どうやってそれを実現させるのか分かりません。結局のところ、それは不可能かもしれません。 – Ben

0
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" 
関連する問題