我正在尝试在F#中实现“try cast”运算符。约束的子类型不起作用。
例如,我想用C#做什么:
static A TryCast<TSuper, TSub, A>(
Func<TSub, A> f,
Func<TSuper, A> g,
TSuper x)
where TSub : TSuper
=>
x is TSub sub ? f(sub) : g(x);
F#中的等价物应为:
let tryCast<'super, 'sub when 'sub :> 'super>
(f : 'sub -> 'a) (g: 'super -> 'a) (x : 'super) : 'a =
match x with
| :? 'sub as sub -> f sub
| x -> g x
或者
...
if x :? 'sub then f (x :?> 'sub) else g x
然而,它给了我一个错误“'sub”在“when”子句中被限制为总是'super'。 这似乎表明F#不支持这一点。我觉得奇怪的是我可以在C#中做到这一点。
所以问题是:这可以在F#中完成吗?
答案 0 :(得分:2)
感谢链接解释它确实是F#限制: How to constrain one type parameter by another
我想分享我找到的针对具体案例的(次优)解决方法:
let tryCastWith
(success : 'sub -> 'a) (fallback: 'super -> 'a) (x : 'super) : 'a =
let o = box x
if o :? 'sub then success (o :?> 'sub) else fallback x
更具体地说,我实际想要的功能是这样的:
let tryCast (x : 'super) : Choice<'sub, 'super> =
tryCastWith Choice1Of2 Choice2Of2 x
使铸造与消费脱钩。为了使用第二个函数,有必要让F#推断'sub'或者给出一个显式类型注释。