具有类似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的字符串表示形式,而不管其实际类型是什么。
答案 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()