具有类型约束的泛型类上的F#模式匹配

时间:2020-06-30 09:36:12

标签: f# pattern-matching

具有类似C#的类

public abstract class ValueAttrProxy<T> : IAttrProxy where T : IEquatable<T>
{
    public T Value { get; }
    ...
}

在F#中,当我尝试进行模式匹配时,如下所示:

let attrValue (attr:IAttrProxy) =
    match attr with
    | :? ValueAttrProxy<'a> as attr -> attr.Value.ToString()

类型推断似乎可以正常工作,但是发送到交互失败并显示以下错误:

错误FS0071:将默认类型'IEquatable <'a>'应用到类型推断变量时,类型约束不匹配。类型“ a”和“ IEquatable <'a>”不能统一。考虑添加更多类型约束

我有点困惑,问题出在哪里,或者期望附加类型注释在哪里?

尝试以匹配模式指定IEquatable <'a>

| :? ValueAttrProxy<IEquatable<'a>> as attr -> attr.Value.ToString()

然后,甚至类型推断也会失败,并使用相同的错误消息在模式下加下划线。 如果我将通用参数限制为int这样的特定类型,则它可以工作,但要点是,我只想要Value的字符串表示形式,而不管其实际类型是什么。

1 个答案:

答案 0 :(得分:3)

问题在于,当您编写:? ValueAttrProxy<'a>时,编译器需要静态地推断'a的类型。这不是在运行时根据该值确定的类型。如果没有限制,编译器仍会很乐意对此进行编译,但是它将使用obj作为'a的默认类型。

该问题与pattern matching against seq<'a>上的最新问题基本相同,在该问题上您完全相同。那里的答案显示了如何使用反射解决问题,这同样适用于您的情况。

如果您控制着C#类,那么通过以下方式将BoxedValue属性添加到非通用接口会容易得多:

public interface IAttrProxy {
    public object BoxedValue { get; }
    // (...)
}
public abstract class ValueAttrProxy<T> :
  IAttrProxy where T : IEquatable<T> {
    public T Value { get; }
    // (...)
}

然后您可以对IAttrProxy进行模式匹配并直接访问该值:

let attrValue (attr:IAttrProxy) =
    attr.BoxedValue.ToString()
相关问题