F#类型参数缺少一个约束 [英] F# A type parameter is missing a constraint

查看:93
本文介绍了F#类型参数缺少一个约束的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图为一个包装类定义一个通用的加法运算符。到目前为止,我有这样的:(从实际代码中简化)

  type Wrap< a> = 
| (+)(Wrap x,Wrap y)= Wrap(x + y)

让内联addSelf x = x + x

确实有效:

  let i = addSelf(Wrap 1)//返回Wrap 2 
让f = addSelf(Wrap 1)//返回Wrap 2.0

,但以下addSelf替代方法不能编译

  let inline addSelf'( Wrap x)=(Wrap x)+(Wrap x)//编译错误

给出错误FS0193:一个类型参数缺少一个约束'when(^ a or ^?15169):(静态成员(+):^ a * ^?15169 - > ^?15170)'

为什么addSelf工作正常时,受限制的addSelf不工作?谢谢!

解决方案

如果您查看FSI中Wrap的定义,您将看到定义了静态(+)运算符只适用于支持限制的类型,但Wrap本身是为任何类型定义的。



在编写第一个版本时,类型推断会为您添加限制...但你的第二个版本允许任何类型的x(甚至对于不支持静态(+)运算符的x)。



Ie第二个版本表明可以编写一个支持任何类型的Wrap'T'的函数,尽管不能保证'T支持+运算符。'

编辑:
Tomas指出,这是可能的,但您必须使用一个特殊的语法来定义调用哪个成员,以下工作:

  let inline addSelf(x:Wrap< _> = 
((^ a或^ b):(静态成员(+):^ a * ^ b - > ^ c)(x ,x))


I'm trying to define a generic addition operator for a wrapper class. So far I have this: (simplified from the actual code)

type Wrap<'a> =
    | Wrap of 'a
    static member inline (+) (Wrap x, Wrap y) = Wrap (x + y)

let inline addSelf x = x + x

and indeed it works:

let i = addSelf (Wrap 1)  // returns Wrap 2
let f = addSelf (Wrap 1.) // returns Wrap 2.0

but the following alternative to addSelf does not compile

let inline addSelf'  (Wrap x) = (Wrap x) + (Wrap x) // compile error

giving error FS0193: A type parameter is missing a constraint 'when ( ^a or ^?15169) : (static member ( + ) : ^a * ^?15169 -> ^?15170)'

Why does the more restricted addSelf' not work when addSelf works fine? Thanks!

解决方案

If you look at the definition of Wrap in FSI, you will see that the static (+) operator is defined only for types that support the restriction, yet Wrap itself is defined for any types.

When write the first version, the type inference adds that restriction for you... but your second version allows any type for x (even for x that do not support the static (+) operator).

I.e. the second version suggest that it is possible to write a function that would support any type of Wrap<'T> although there's no guarantee 'T supports the + operator.

edit: As Tomas pointed out, it's possible but you have to use a special syntax that defines which member to call, the following works:

let inline addSelf (x : Wrap<_>) =
    ((^a or ^b): (static member (+) : ^a * ^b -> ^c) (x,x))

这篇关于F#类型参数缺少一个约束的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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