5

是否可以在有区别的联合类型声明中使用活动模式?

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

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

3 回答 3

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
于 2012-12-12T15:22:45.407 回答
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
于 2012-12-12T14:49:34.373 回答
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.
于 2012-12-12T14:43:07.160 回答