【发布时间】:2015-05-22 16:15:57
【问题描述】:
我不明白为什么下面的代码不能编译
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)
如果您查看 2“创建者...”函数 - 它们都给出编译错误..
这个表达式应该有 int 类型...但是这里有 输入字符串
我可以看到 F# 将 getAsParam 方法的返回类型推断为 int,因为它是它遇到的第一个。但是,为什么它不决定使用泛型返回类型呢?
如您所见,我已尝试在 creatorWithTypeAnnotation 方法中进行函数签名 - 但这没有任何影响。
我被难住了!我如何强制它识别 getAsParam 函数应该返回一个泛型?
【问题讨论】:
-
基本上当它看到第一个(
Apple)时,类型推断会将getAsParam专门化为string -> Apple,所以当然你的第二次使用它(对于Dog)必须失败 - 如果你删除有错误的部分,你甚至可以看到它 - 编译器应该警告你它将'a限制为Apple- 试着想想你将如何编写一个返回真正 generic'a没有作弊(反射,默认值,...) -
但是.. 我如何强制 getAsParam 具有通用返回类型?注意 - 如果我对 getAsParams 的论点之一是 'a ...,我可以做到这一点,但我不想这样做
-
如果你使用接口而不是
getAsParam的函数,你可以欺骗进入这个过程@ -
只需将
getAsParam中的'a视为createorWithAnnotation的通用参数 - 看看为什么这里不能是两个不同的东西? - 所以如果你需要两个不同的结果,你也必须使用两个不同的getAsParam1和getAsParam2参数
标签: generics f# type-inference