我正在尝试在 F# 中编写一个方法,该方法根据传递到方法中的值的类型返回泛型类型的新实例。在 FSI 中:
open System.Collections.Generic
type AttributeIndex<'a>() =
inherit SortedDictionary<'a, HashSet<int array>>()
let getNewIndexForValue (value: obj) : AttributeIndex<_> =
match value with
| :? string -> new AttributeIndex<string>()
| :? int -> new AttributeIndex<int>()
| :? float -> new AttributeIndex<float>()
| :? bool -> new AttributeIndex<bool>()
| _ -> failwith "bad value type"
let someIndexes = [
getNewIndexForValue 9;
getNewIndexForValue "testString";
getNewIndexForValue false;
getNewIndexForValue 5.67;
]
someIndexes;;
编译不会出错
error FS0001: Type mismatch. Expecting a
AttributeIndex<string><br/>
but given a
AttributeIndex<int><br/>
The type 'string' does not match the type 'int'
我似乎无法弄清楚如何根据传递给函数的值参数的类型来获取具有类型参数的 Attribute 实例。我尝试了其他几个变体,但都导致了相同的类型不匹配错误。任何帮助将不胜感激。谢谢!!
更新:
感谢您的回答。我现在明白了。所以现在我试图让我的“getNewIndexForValue”返回一个非通用的基本 AttributeIndex 类。我已经在 C# 中实现了它,它可以按预期编译和运行:
using System;
using System.Collections.Generic;
namespace Example {
public class AttributeIndexBase : SortedDictionary<object, HashSet<int[]>> { }
public class AttributeIndex<T> : AttributeIndexBase {
public void AddToIndex(T indexValue, int[] recordKey) {
if (!this.ContainsKey(indexValue)) {
this.Add(indexValue, new HashSet<int[]> { recordKey });
}
else {
this[indexValue].Add(recordKey);
}
}
}
class Program {
static int Main(string[] args) {
var intIdx = GetIndexForValue(32);
var boolIdx = GetIndexForValue(true);
var doubleIdx = GetIndexForValue(45.67);
var someIndexes = new List<AttributeIndexBase> {
intIdx,
boolIdx,
doubleIdx
};
return 0;
}
static AttributeIndexBase GetIndexForValue(object value) {
switch (value.GetType().Name.ToLower()) {
case "int32" :
return new AttributeIndex<int>();
case "single" :
return new AttributeIndex<float>();
case "double" :
return new AttributeIndex<double>();
case "boolean" :
return new AttributeIndex<bool>();
default :
throw new ArgumentException("The type of the value param is not allowed", "value");
}
}
}
}
但是,尝试将其移植到 F# 是行不通的:
module example
open System
open System.Collections.Generic
type AttributeIndexBase() =
inherit SortedDictionary<obj, HashSet<int array>>()
type AttributeIndex<'a>() =
inherit AttributeIndexBase()
let getNewIndexForValueType (value: ValueType) : AttributeIndexBase =
match value with
| :? int -> new AttributeIndex<int>()
| :? float -> new AttributeIndex<float>()
| :? bool -> new AttributeIndex<bool>()
| _ -> failwith "bad value type"
let someIndexes = [
getNewIndexForValueType 9;
getNewIndexForValueType false;
getNewIndexForValueType 5.67;
]
在我看来,这似乎是一个非常直接的端口(除了在 F# 版本中我将其限制为 ValueType),但是我收到错误:
error FS0001: This expression was expected to have type
AttributeIndexBase<br/>
but here has type
AttributeIndex<int>
F# 真的不像 C# 那样支持从子类型到父类型的转换吗?
最佳答案
您的最新代码几乎可以工作,但 F# 要求您在这种情况下显式向上转换为 AttributeIndexBase
。至少有两种方法可以做到这一点:您可以使用 upcast
关键字,或者您可以使用 :>
转换运算符。
第一个选项看起来像这样:
let getNewIndexForValueType (value: ValueType) : AttributeIndexBase =
match value with
| :? int -> upcast new AttributeIndex<int>()
| :? float -> upcast new AttributeIndex<float>()
| :? bool -> upcast AttributeIndex<bool>()
| _ -> failwith "bad value type"
虽然第二个看起来像这样:
let getNewIndexForValueType (value: ValueType) : AttributeIndexBase =
match value with
| :? int -> new AttributeIndex<int>() :> _
| :? float -> new AttributeIndex<float>() :> _
| :? bool -> new AttributeIndex<bool>() :> _
| _ -> failwith "bad value type"
关于.net - 类型不匹配错误。 F# 类型推断失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3532637/