Использование активных шаблонов в объявлениях различаемого типа объединения

Можно ли использовать активные шаблоны в объявлениях различного типа объединения?

Чтобы быть более точным, рассмотрим следующий игрушечный пример:

type T = 
    | A of int
    | B

let (|Negative|_|) t = 
    match t with
    | A n when n < 0 -> Some ()
    | _ -> None

let T_ToString = function
    | Negative () -> "negative!"
    | _ -> "foo!"

Теперь предположим, что я хочу переопределить ToString() в T. Внутри объявления типа T я не могу ссылаться на T_ToString, так как T_ToString еще не объявлен в этой точке. Я не могу переместить активный шаблон и T_ToString до ToString(), потому что T еще не объявлен в этой точке. Но это тоже не работает:

type T = 
    | A of int
    | B

    static member (|Negative|_|) t = 
        match t with
        | A n when n < 0 -> Some ()
        | _ -> None

    override this.ToString () = 
        match this with
        | Negative () -> "negative!"
        | _ -> "foo!"

3 ответа

Ваш вопрос предполагает, что тестирование на негатив является внутренней операцией Tтак что это должно быть частью его определения. Определение свойства является одним из способов сделать это:

type T = 
  | A of int
  | B

  member this.IsNegative = 
    match this with
    | A n -> n < 0
    | _ -> false

  override this.ToString() = 
    if this.IsNegative then "negative!"
    else "foo!"

Я не уверен, что активный шаблон все еще нужен, но если это так, то он тривиален:

let (|Negative|_|) (x: T) = if x.IsNegative then Some() else None

Это не самое лучшее решение, но вы можете сделать это:

type T = 
    | A of int
    | B

    static member internal ActivePattern t =
        match t with
        | A n when n < 0 -> Some ()
        | _ -> None

    override this.ToString () = 

        let (|Negative|_|) = T.ActivePattern

        match this with
        | Negative () -> "negative!"
        | _ -> "foo!"

let (|Negative|_|) = T.ActivePattern

Хорошо, я думаю, что нашел решение: сначала объявить тип, затем объявить активный шаблон вне его, и, наконец, дополнить тип реализацией переопределения ToString().

type T = 
    | A of int
    | B

let (|Negative|_|) t = 
    match t with
    | A n when n < 0 -> Some ()
    | _ -> None

type T with
    override this.ToString() = 
        match this with
        | Negative () -> "negative!"
        | _ -> "foo!"

Тем не менее, это не очень приятно, так как я получаю предупреждение

warning FS0060: Override implementations in augmentations are now deprecated. Override implementations should be given as part of the initial declaration of a type.
Другие вопросы по тегам