Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 类型不匹配错误。F#类型推断失败?_.net_F#_Functional Programming_Type Inference_F# Interactive - Fatal编程技术网

.net 类型不匹配错误。F#类型推断失败?

.net 类型不匹配错误。F#类型推断失败?,.net,f#,functional-programming,type-inference,f#-interactive,.net,F#,Functional Programming,Type Inference,F# Interactive,我试图在F#中编写一个方法,该方法根据传入该方法的值的类型返回泛型类型的新实例。在FSI中: open System.Collections.Generic type AttributeIndex<'a>() = inherit SortedDictionary<'a, HashSet<int array>>() let getNewIndexForValue (value: obj) : AttributeIndex<_> =

我试图在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;;
open System.Collections.Generic
类型AttributeIndex()
让getNewIndexForValue(值:obj):AttributeIndex=
匹配值
| :? 字符串->新属性索引()
| :? int->新属性索引()
| :? 浮动->新属性索引()
| :? bool->新属性索引()
|_u824;->故障类型为“错误值类型”
让一些索引=[
getNewIndexForValue 9;
getNewIndexForValue“testString”;
getNewIndexForValue为false;
getNewIndexForValue 5.67;
]
一些指数;;
这不会编译时出错

错误FS0001:类型不匹配。期待
属性索引
但是给一个 属性索引
类型“string”与类型“int”不匹配。

我似乎不知道如何根据传递到函数中的value参数的类型获取类型为param的属性实例。我尝试了其他几种变体,但都会导致相同的类型不匹配错误。任何帮助都将不胜感激。谢谢

更新:

谢谢你的回答。我现在明白了。所以现在我尝试让我的“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");
            }
        }
    }
}
使用系统;
使用System.Collections.Generic;
名称空间示例{
公共类AttributeIndexBase:SortedDictionary{}
公共类AttributeIndex:AttributeIndexBase{
public void AddToIndex(T indexValue,int[]记录键){
如果(!this.ContainsKey(indexValue)){
Add(indexValue,新HashSet{recordKey});
}
否则{
此[indexValue].Add(recordKey);
}
}
}
班级计划{
静态int Main(字符串[]args){
var intIdx=GetIndexForValue(32);
var boolIdx=GetIndexForValue(真);
var doubleIdx=GetIndexForValue(45.67);
var someindex=新列表{
intIdx,
布利克斯,
双IDX
};
返回0;
}
静态属性索引数据库GetIndexForValue(对象值){
开关(value.GetType().Name.ToLower()){
案例“int32”:
返回新的AttributeIndex();
“单一”情况:
返回新的AttributeIndex();
“双重”情况:
返回新的AttributeIndex();
案例“布尔”:
返回新的AttributeIndex();
违约:
抛出新ArgumentException(“不允许值参数的类型”,“值”);
}
}
}
}
但是,尝试将其移植到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;
     ]
模块示例
开放系统
open System.Collections.Generic
类型AttributeIndexBase()=
继承SortedDictionary()

键入AttributeIndex无法为函数返回值提供通用参数的事实是一个红色标志:

let getNewIndexForValue (value: obj) : AttributeIndex< ?? what goes here > =
让getNewIndexForValue(值:obj):AttributeIndex<??这里有什么>=
getNewIndexForValue
函数必须为
'a
参数选择一种类型;
'a
类型参数可以是string、int、float或bool,但不能同时为所有参数


一种可能是引入一个非泛型的
AttributeIndex
类,该类的
AttributeIndex问题是您试图获得一个非泛型方法来返回不同的绑定泛型类型。这是不可能的。这相当于在C#中尝试以下内容


让我们看看这一行:

let getNewIndexForValue (value: obj) : AttributeIndex<_> =
让getNewIndexForValue(值:obj):AttributeIndex=
AttributeIndex
中的下划线对编译器意味着:嘿,找出要插入的类型。它基本上只保存了一些击键。如果您返回一个
属性索引
,编译器将分别推断
字符串
,或
bool
int

您要做的是在这里返回不同的类型。这不是关于某种类型,而是关于允许的任何类型。这与Java的通用通配符基本不同

  • Java的
    列表
    是任何可能值的列表(如
    对象
    可以)

  • F#的
    列表
    正好是一种类型的列表

您需要的是Java通配符,在.NET下,您可以通过co/contravariant类型在那里进行表示


因此,您需要
AttributeIndex

我最初将此作为一条评论发布,但实际上这是“答案”:

你打算用它做什么 “someIndexes”之后

除非你具体说明,否则任何“答案”都只是空泛的猜测。我们无法提供有关如何克服此“类型错误”的规定性建议,因为根据您最终打算如何使用数据,有许多可能的克服方法。我认为@JaredPar的答案最有可能是你想要的,但这基本上是我试图成为通灵者(以及其他所有答案)


一旦您对每个索引指定了“您想做什么”,那么这就意味着所有索引都需要支持一个公共接口或基类,这就是您的答案。

其他人都是对的,但我想我可以补充一点解释

F#中的每个表达式都有一个类型。在F#中,“if a then b else c”是一个表达式,返回b或c。要使其工作,b和c必须具有相同的类型。“match…”也是一个表达式,返回其中一个子句的值。这意味着每个子句必须具有相同的类型

您的匹配表达式试图违反此规则。每个子句都有不同的类型
type AttributeIndex =
  member GetValue : object -> HashSet<int array>

type AttributeIndex<'a> = 
  inherit AttributeIndex
  inherit IDictionary<'a, HashSet<int array>>
let getNewIndexForValue (value: obj) : AttributeIndex<_> =
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"