Generics FSharp:具有泛型的类型推断
我不明白为什么下面的代码不能编译Generics FSharp:具有泛型的类型推断,generics,f#,type-inference,Generics,F#,Type Inference,我不明白为什么下面的代码不能编译 module GenericsTest = open System type Dog = { name:string } type Apple = { size:int } let get<'a> (id:string) = Activator.CreateInstance<'a>() let creatorInferred
module GenericsTest =
open System
type Dog = {
name:string
}
type Apple = {
size:int
}
let get<'a> (id:string) =
Activator.CreateInstance<'a>()
let creatorInferred getAsParam =
let apple = {
name = getAsParam "some-apple"
}
let dog = {
size = getAsParam "some-dog"
}
(apple, dog)
let creatorWithTypeAnnotation (getAsParam:string->'a) =
let apple = {
name = getAsParam "some-apple"
}
let dog = {
size = getAsParam "some-dog"
}
(apple, dog)
模块GenericsTest=
开放系统
类型狗={
名称:string
}
苹果类型={
大小:int
}
让我们开始
让creatorInferred getAsParam=
让苹果={
name=getAsParam“一些苹果”
}
让狗{
大小=getAsParam“一些狗”
}
(苹果,狗)
让creatorWithTypeAnnotation(getAsParam:string->'a)=
让苹果={
name=getAsParam“一些苹果”
}
让狗{
大小=getAsParam“一些狗”
}
(苹果,狗)
如果查看2“creator…”函数,它们都会给出编译错误
此表达式的类型应为int。。。但是这里有
类型字符串
我可以看到,F#推断getAsParam方法的返回类型为int,因为它是它遇到的第一个返回类型。但是,为什么不决定使用泛型返回类型呢
正如您所看到的,我已经尝试在creatorWithTypeAnnotation方法中为函数签名创建一个函数,但这没有任何影响
我被难住了!我如何强迫它认识到getAsParam函数应该返回一个泛型?下面是一个快速的F#交互式会话,通过使用一个接口(它必须是某种成员,当然也可以是类上的一个方法):
>键入ipram=abstract getParam:string->'a;;
IPRAM型=
接口
抽象成员getParam:string->'a
结束
>让createWith(p:ipram):int*bool=(p.getParam“a”,p.getParam“b”);;
val createWith:p:IParam->int*bool
>让test={new IParam with member _u.getParam s=Unchecked.defaultof};;
val测试:IParam
>进行测试;;
val it:int*bool=(0,false)
不过,您可能会发现实现一些更健全的ipram实例并不容易 这里是一个快速的F#交互式会话,我指的是通过使用接口作弊(它必须是某种成员
,因此它当然也可以是类中的一种方法):
>键入ipram=abstract getParam:string->'a;;
IPRAM型=
接口
抽象成员getParam:string->'a
结束
>让createWith(p:ipram):int*bool=(p.getParam“a”,p.getParam“b”);;
val createWith:p:IParam->int*bool
>让test={new IParam with member _u.getParam s=Unchecked.defaultof};;
val测试:IParam
>进行测试;;
val it:int*bool=(0,false)
不过,您可能会发现实现一些更健全的ipram实例并不容易 这里是一个快速的F#交互式会话,我指的是通过使用接口作弊(它必须是某种成员
,因此它当然也可以是类中的一种方法):
>键入ipram=abstract getParam:string->'a;;
IPRAM型=
接口
抽象成员getParam:string->'a
结束
>让createWith(p:ipram):int*bool=(p.getParam“a”,p.getParam“b”);;
val createWith:p:IParam->int*bool
>让test={new IParam with member _u.getParam s=Unchecked.defaultof};;
val测试:IParam
>进行测试;;
val it:int*bool=(0,false)
不过,您可能会发现实现一些更健全的ipram实例并不容易 这里是一个快速的F#交互式会话,我指的是通过使用接口作弊(它必须是某种成员
,因此它当然也可以是类中的一种方法):
>键入ipram=abstract getParam:string->'a;;
IPRAM型=
接口
抽象成员getParam:string->'a
结束
>让createWith(p:ipram):int*bool=(p.getParam“a”,p.getParam“b”);;
val createWith:p:IParam->int*bool
>让test={new IParam with member _u.getParam s=Unchecked.defaultof};;
val测试:IParam
>进行测试;;
val it:int*bool=(0,false)
不过,您可能会发现实现一些更健全的ipram实例并不容易 正如Carsten所暗示的,类型变量都是在编译时解析的。如果将getAsParam
定义为string->'a
,则不会阻止编译时解析'a
。因为它不能在编译时解析为两种不同的类型,所以编译失败
以你的例子为例:
let creatorWithTypeAnnotation (getAsParam:string->'a) =
let apple = {
name = getAsParam "some-apple"
}
let dog = {
size = getAsParam "some-dog"
}
这也可以这样声明(我将使用'A
而不是'A
,因为预期的约定是小写类型变量用于编译器推断的类型):
让creatorWithTypeAnnotation正如Carsten所暗示的,类型变量都在编译时解析。如果将getAsParam
定义为string->'a
,则不会阻止编译时解析'a
。因为它不能在编译时解析为两种不同的类型,所以编译失败
以你的例子为例:
let creatorWithTypeAnnotation (getAsParam:string->'a) =
let apple = {
name = getAsParam "some-apple"
}
let dog = {
size = getAsParam "some-dog"
}
这也可以这样声明(我将使用'A
而不是'A
,因为预期的约定是小写类型变量用于编译器推断的类型):
让creatorWithTypeAnnotation正如Carsten所暗示的,类型变量都在编译时解析。如果将getAsParam
定义为string->'a
,则不会阻止编译时解析'a
。因为它不能在编译时解析为两个不同的t
let creatorWithTypeAnnotation<'A> (getAsParam:string->'A) =
let apple = {
name = getAsParam "some-apple"
}
let dog = {
size = getAsParam "some-dog"
}