Извлечь и сравнить конструкторы размеченных объединений - PullRequest
1 голос
/ 28 мая 2020

Для следующих типов:

type Pos = {line:int; col:int}
let Pos line col = {line = line; col = col}

type Token =
    | ADD of Pos
    | INT of Pos * int

let ts = [INT (Pos 1 1, 4);ADD (Pos 1 2);INT (Pos 1 3, 7)]

type Parser<'a> = Parser of (Token list -> 'a option * Token list)

let run p ts = let (Parser pfun) = p in pfun ts

При написании функции, которая проверяет, принадлежит ли первый токен в списке к определенному типу токена, например:

let token (tok: Token) : Parser<Token> = Parser <| fun lst ->
    match lst with
    | [] -> None, lst
    | t::ts -> if t = tok then Some t, ts else None, lst

Есть ли способ обобщить это так, чтобы параметр tok мог просто быть любым из конструкторов из Token, то есть ADD или INT, и без параметров, данных этим конструкторам?

Таким образом, функция token может быть запущена как run (token ADD) ts вместо run (token (ADD (Pos 1 1))) ts.

То, что я пробовал до сих пор, - это использовать GetType() через который я могу получить имя конструктора в виде строки для текущего токена t, проверяемого следующим образом:

t.GetType().Name     // Output: "INT" or "ADD" as strings

Однако, если я просто передаю конструктор INT в качестве параметра tok в token, tok.GetType().Name не приводит к "INT", так как конструктор INT имеет тип Pos * int -> Token ...

Возможно, чтобы реализовать вышеприведенную идею, основанную на GetType(), решение могло бы быть, чтобы найти способ преобразовать INT или ADD в строки "INT" или "ADD" соответственно.

1 Ответ

1 голос
/ 28 мая 2020

Возможно, я не понял.

Вы можете определить и передать сопоставитель

let matchAdd = function
    | ADD p as t -> Some t
    | _ -> None
let matchInt = function
    | INT _ as t -> Some t
    | _ -> None

let token2 matcher : Parser<Token> = Parser <| fun lst ->
    match lst with
    | [] -> None, lst
    | t::ts -> 
        match (matcher t) with 
        | Some t -> Some t, ts
        | None -> None, lst

?

...