在区分联合类型声明中使用活动模式

时间:2012-12-12 14:31:27

标签: f# discriminated-union active-pattern

是否可以在被描述的联合类型声明中使用活动模式?

更准确地说,请考虑以下玩具示例:

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!"

现在假设我要覆盖T中的ToString()。在T的类型声明中我不能引用T_ToString,因为T_ToString尚未在那时声明。我无法在ToString()之前移动活动模式和T_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 个答案:

答案 0 :(得分:4)

您的问题表明,对负面进行测试是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

答案 1 :(得分:3)

这不是最好的解决方案,但你可以这样做:

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

答案 2 :(得分:2)

好的,我认为我找到了一个解决方案:首先声明类型,然后在其外部声明活动模式,最后使用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.