类型不匹配错误。 F#类型推断失败? [英] Type mismatch error. F# type inference fail?

查看:106
本文介绍了类型不匹配错误。 F#类型推断失败?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆