Как мне изменить мой класс Queue, чтобы позволить пользователям создавать пустые очереди неопределенного типа в F #? - PullRequest
6 голосов
/ 29 мая 2009

Я создал неизменный Queue в F # следующим образом:

type Queue<'a>(f : 'a list, r : 'a list) =    
    let check = function
        | [], r -> Queue(List.rev r, [])
        | f, r -> Queue(f, r)

    member this.hd =
        match f with
        | [] -> failwith "empty"
        | hd :: tl -> hd

    member this.tl =
        match f, r with
        | [], _ -> failwith "empty"
        | hd::f, r -> check(f, r)

    member this.add(x) = check(f, x::r)

    static member empty : Queue<'a> = Queue([], [])

Я хочу создать экземпляр пустого Queue, однако я получаю исключение ограничения значения:

> let test = Queue.empty;;

  let test = Queue.empty;;
  ----^^^^

C: \ Documents and Settings \ juliet \ Локальные настройки \ Temp \ stdin (5,5): ошибка FS0030: Ограничение стоимости. Значение 'test' было выведено, чтобы иметь общий тип val test: Queue <'_ a> Либо определите «тест» как простой термин данных, сделайте его функцией с явным аргументы или, если вы не планируете, чтобы он был универсальным, добавьте аннотацию типа.

По сути, я хочу, чтобы в модуле Set была та же функциональность, что позволяет мне писать:

> let test = Set.empty;;

val test : Set<'a>

Как изменить класс Queue, чтобы пользователи могли создавать пустые очереди?

1 Ответ

6 голосов
/ 29 мая 2009

Вам нужно использовать GeneralizableValueAttribute, а-ля:

type Queue<'a>(f : 'a list, r : 'a list) =  // '
    let check = function
        | [], r -> Queue(List.rev r, [])
        | f, r -> Queue(f, r)

    member this.hd =
        match f with
        | [] -> failwith "empty"
        | hd :: tl -> hd

    member this.tl =
        match f, r with
        | [], _ -> failwith "empty"
        | hd::f, r -> check(f, r)

    member this.add(x) = check(f, x::r)
module Queue =    
    [<GeneralizableValue>]
    let empty<'T> : Queue<'T> = Queue<'T>([], []) // '

let test = Queue.empty
let x = test.add(1)       // x is Queue<int>
let y = test.add("two")   // y is Queue<string>

Подробнее об этом можно прочитать в спецификации языка .

...