具有类型约束的泛型 class 上的 F# 模式匹配
F# Pattern matching on generic class that has a type constraint
有一个 C# class 喜欢
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),那么它就可以工作,但关键是我只想要值的字符串表示形式,而不管它的实际类型是什么。
问题在于,当您编写 :? ValueAttrProxy<'a>
时,编译器需要静态推断 'a
的类型。这不是在运行时根据值确定的类型。如果没有约束,编译器仍然会愉快地编译它,但它会使用 obj
作为 '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()
有一个 C# class 喜欢
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),那么它就可以工作,但关键是我只想要值的字符串表示形式,而不管它的实际类型是什么。
问题在于,当您编写 :? ValueAttrProxy<'a>
时,编译器需要静态推断 'a
的类型。这不是在运行时根据值确定的类型。如果没有约束,编译器仍然会愉快地编译它,但它会使用 obj
作为 '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()