类型不匹配错误。 F#类型推断失败? [英] Type mismatch error. F# type inference fail?
问题描述
我试图在F#中编写一个方法,它根据传入方法的值的类型返回一个泛型类型的新实例。在FSI中:
打开System.Collections.Generic
类型AttributeIndex<'a>()=
继承SortedDictionary<'a,HashSet< int array>>()
let getNewIndexForValue(value:obj):AttributeIndex< _> =
与
|匹配值:?字符串 - >新的AttributeIndex< string>()
| :? int - >新的AttributeIndex< int>()
| :?浮动 - >新的AttributeIndex< float>()
| :? bool - >新的AttributeIndex< bool>()
| _ - > failwith坏值类型
let someIndexes = [
getNewIndexForValue 9;
getNewIndexForValuetestString;
getNewIndexForValue false;
getNewIndexForValue 5.67;
]
someIndexes ;;
不会编译错误
错误FS0001:类型不匹配。期望
AttributeIndex<字符串>
,但给出
AttributeIndex< int>
类型'字符串'与'int'类型不匹配
我似乎无法弄清楚如何根据传入参数的value参数的类型来获取类型参数的Attribute实例功能。我已经尝试了其他一些变体,但都导致相同类型的不匹配错误。任何帮助将不胜感激。感谢!!
更新:
感谢您的回答。我现在明白了。所以现在我试图让我的'getNewIndexForValue'返回一个非泛型的基础AttributeIndex类。我已经在C#中实现了这个功能,并且按照我的预期进行编译和运行:
using System;
使用System.Collections.Generic;
namespace示例{
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);
$ b class程序{
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
};
返回0;
}
$ b $静态AttributeIndexBase GetIndexForValue(对象值){
switch(value.GetType()。Name.ToLower()){
caseint32:
返回新的AttributeIndex< int>();
casesingle:
返回新的AttributeIndex< float>();
casedouble:
返回新的AttributeIndex< double>();
caseboolean:
返回新的AttributeIndex< bool>();
默认值:
抛出新的ArgumentException(值参数的类型不允许,value);
}
}
}
}
然而, ,试图移植到F#不起作用:
模块示例
打开系统
打开System.Collections.Generic
类型AttributeIndexBase()=
继承SortedDictionary< obj,HashSet< int array>>()
类型AttributeIndex<' a>()=
继承AttributeIndexBase()
getNewIndexForValueType(value:ValueType):AttributeIndexBase =
与
匹配值| :? int - >新的AttributeIndex< int>()
| :?浮动 - >新的AttributeIndex< float>()
| :? bool - >新的AttributeIndex< bool>()
| _ - > failwith坏值类型
let someIndexes = [
getNewIndexForValueType 9;
getNewIndexForValueType false;
getNewIndexForValueType 5.67;
]
在我看来,这是一个非常直接的端口(除了F#版本我限制它只是ValueType),但是我得到错误:
错误FS0001:此表达式预计有类型
AttributeIndexBase
但这里有类型
AttributeIndex< int>
F#是否真的不支持转换的子类到像C#这样的父类型?
您的最新代码几乎可以工作,但F#要求您明确向上 AttributeIndexBase
在这种情况下。至少有两种方法可以做到这一点:您可以使用 upcast
关键字,或者您可以使用:>
转换运算符。
第一个选项如下所示:
让getNewIndexForValueType(value:ValueType):AttributeIndexBase =
与
匹配值| :? int - >上传新的AttributeIndex< int>()
| :?浮动 - >上传新的AttributeIndex< float>()
| :? bool - > upcast AttributeIndex< bool>()
| _ - > failwithbad value type
第二种看起来像这样:
let getNewIndexForValueType(value:ValueType):AttributeIndexBase =
与
匹配值| :? int - >新的AttributeIndex< int>():> _
| :?浮动 - >新的AttributeIndex< float>():> _
| :? bool - >新的AttributeIndex< bool>():> _
| _ - > failwith坏值类型
I'm trying to write a method in F# that returns a new instance of a generic type based upon the type of a value passed into the method. In 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;;
This does not compile with error
error FS0001: Type mismatch. Expecting a
AttributeIndex<string>
but given a
AttributeIndex<int>
The type 'string' does not match the type 'int'
I can't seem to figure out how to get an instance of Attribute with the type param based upon the type of the value parameter passed into the function. I've tried a couple other variation, but all result in the same type mismatch error. Any help would be greatly appreciated. Thanks!!
UPDATE:
Thanks for the answers. I get it now. So now I'm trying to have my 'getNewIndexForValue' return a non-generic base AttributeIndex class. I've implemented this in C# and it compiles and runs as I expect:
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");
}
}
}
}
However, trying to port this to F# does not work:
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;
]
This seems to me to be a pretty straight port (except in the F# version I'm constraining it to just ValueType), however I get error:
error FS0001: This expression was expected to have type
AttributeIndexBase
but here has type
AttributeIndex<int>
Does F# really just not support a cast of child to parent type like C# does?
Your latest code will almost work, but F# requires you to explicitly upcast to AttributeIndexBase
in this case. There are at least two ways to do this: you could use the upcast
keyword or you could use the :>
conversion operator.
The first option would look like this:
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"
While the second would look like this:
let getNewIndexForValueType (value: ValueType) : AttributeIndexBase =
match value with
| :? int -> new AttributeIndex<int>() :> _
| :? float -> new AttributeIndex<float>() :> _
| :? bool -> new AttributeIndex<bool>() :> _
| _ -> failwith "bad value type"
这篇关于类型不匹配错误。 F#类型推断失败?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!