我尝试了以下内容:
let inline (|OpAdd|_|) (aty:Type, x:obj, y:obj) =
if aty.Equals(typeof<'a>) then Some(box ((unbox<'a> x) + (unbox<'a> y)))
else None
//FSI given signature:
//val inline ( |OpAdd|_| ) : Type * obj * obj -> obj option
哪个没有提供警告或错误,但我无法弄清楚如何在调用网站上传递显式类型参数,似乎'a
始终推断为int
。
当我尝试将显式参数放在定义中时,我会收到一些警告和错误:
let inline (|OpAdd|_|)<'a> (aty:Type, x:obj, y:obj) =
if aty.Equals(typeof<'a>) then Some(box ((unbox<'a> x) + (unbox<'a> y)))
else None
warning FS1189: Type parameters must be placed directly adjacent to the type name, e.g. "type C<'T>", not type "C <'T>"
error FS0001: The declared type parameter 'a' cannot be used here since the type parameter cannot be resolved at compile time
活动模式是否可以具有显式类型参数?如果是这样,我如何定义和使用它们?
答案 0 :(得分:4)
我不确定是否有干净的方法(可能不是,但我可能错了)。
作为一种肮脏的解决方法,您可以添加类型'T
的虚拟参数(当使用具有易于创建的值的基本类型时)或类型Expr<'T>
时(如果不是真的想创建一个实例)。然后,您可以将模式与一些指定类型的伪参数一起使用:
let inline (|OpAdd|_|) (e:Expr<'T>) (aty:Type, x:obj, y:obj) =
if aty.Equals(typeof<'T>) then Some(box ((unbox<'T> x) + (unbox<'T> y)))
else None
let dummy<'T> : 'T = failwith "!"
match (typeof<float>, box 1.1, box 2.1) with
| OpAdd <@ dummy<int> @> res -> res
| OpAdd <@ dummy<float> @> res -> res
| _ -> null
答案 1 :(得分:3)
我认为没有办法做你想做的事,因为我认为这没有任何意义。当使用活动模式时,编译器如何推断类型参数?
即,给定
function
| OpAdd x -> ...
编译器如何知道'a
应该是什么?
在我看来,你有两种选择。一种是在模式的返回类型中反映'a
:
let inline (|OpAdd|_|) (aty:System.Type, x:obj, y:obj) =
if aty.Equals(typeof<'a>) then Some((unbox<'a> x + unbox<'a> y) : 'a)
else None
let (OpAdd(x:int)) = typeof<int>, box 1, box 2
let (OpAdd(y:float)) = typeof<float>, box 3.0, box 4.0
另一种方法是在你的模式的一个输入中反映'a
(也许是沿着Tomas的回答)。