给出以下参数类型
type SomeDU2<'a,'b> =
| One of 'a
| Two of 'a * 'b
我必须使用函数来检查给定的param是否是相应的union情况而不考虑params
let checkOne x =
match x with
| One _ -> true
| _ -> false
let checkTwo x =
match x with
| Two _ -> true
| _ -> false
这非常好用并且符合预期
let oi = checkOne (One 1)
let os = checkOne (One "1")
let tis = checkTwo (Two (1, "1"))
let tsi = checkTwo (Two ("1", 1))
我可以随意切换类型。
现在然而我喜欢将这两个函数组合成一个创建函数
let makeUC () = (checkOne, checkTwo)
然后像这样实例化
let (o,t) = makeUC ()
现在只有它给我这个错误信息
Value restriction. The value 'o' has been inferred to have generic type
val o : (SomeDU2<'_a,'_b> -> bool)
Either make the arguments to 'o' explicit or, if you do not intend for it to be generic, add a type annotation.
val o : (SomeDU2<obj,obj> -> bool)
其实我不想要那个 - 我也不需要那个。 可能是它在F#中缺少更高级别的类型的实例 有办法解决这个问题吗?
修改
实际上我的问题根据@johns的评论不完整。 显然我可以做以下事情
let ro1 = o ((One 1) : SomeDU2<int,int>)
let rt1 = t (Two (1,2))
然后向后推断o
和t
为SomeDU2<int,int> -> bool
类型(我觉得这个向后推断非常奇怪)。那么问题是o
不再允许下面的内容了。
let ro2 = o ((One "1") : SomeDU2<string,int>)
因此,我必须为o
的每个通用参数组合实例化一个特定的SomeDU2
实例。
答案 0 :(得分:3)
即使没有元组,你也会遇到价值限制:
let o = (fun () -> checkOne)()
如果您需要调用函数的结果适用于任何类型的值,那么一种解决方案是使用泛型方法创建名义类型的实例:
type DU2Checker =
abstract Check : SomeDU2<'a,'b> -> bool
let checkOne = {
new DU2Checker with
member this.Check(x) =
match x with
| One _ -> true
| _ -> false }
let checkTwo = {
new DU2Checker with
member this.Check(x) =
match x with
| Two _ -> true
| _ -> false }
let makeUC() = checkOne, checkTwo
let o,t = makeUC()
let false = o.Check(Two(3,4))