Generics Gerenics将参数从';a至obj
鉴于此功能:Generics Gerenics将参数从';a至obj,generics,f#,constraints,Generics,F#,Constraints,鉴于此功能: let endFlow x = match x with | Ok o -> () | Error (e: string) -> exn e |> raise let endFlow<'a, 'T when 'T :> exn> (mkExn : string -> 'T) (x : Result<'a, string>) = match x with | Ok o
let endFlow x =
match x with
| Ok o -> ()
| Error (e: string) ->
exn e |> raise
let endFlow<'a, 'T when 'T :> exn> (mkExn : string -> 'T) (x : Result<'a, string>) =
match x with
| Ok o -> ()
| Error (e: string) ->
mkExn e |> raise
x被决定为结果提升
现在x被解析为结果
。
我是否可以在没有参数obj约束的情况下使用泛型?这是因为您只定义了一个泛型参数。没有'a可以说 以前,当您没有指定任何泛型参数时,编译器可以自由地发明它需要的任何东西来正确地泛化代码。但是,既然您明确表示您的函数只有一个泛型参数
'T
,编译器就不能直接插入并添加一个'a
——这将更改您指定的签名
因此,让我们帮助编译器完成并添加一个'a
参数:
let endFlow<`a, 'T when 'T :> exn> x =
现在签名正是你想要的
然而,即使像这样修复了它,它仍然不会像您期望的那样工作。你看,表达式exn e:?>'T
并不像你想象的那样
表达式exn e
将创建类型为exn
(又称System.Exception
)的对象,然后尝试将其强制转换为未知类型'T
。底层对象肯定不是类型'T
(我们已经知道它是类型exn
),因此这种转换的结果将是null
。和你想象的不太一样,是吗
想想看,你怎么知道类型为'T
的异常完全可以用字符串构造出来呢
如果您确实想抛出调用方定义类型的异常,则必须提供构造此类异常的方法,即提供构造函数:
let endFlow x =
match x with
| Ok o -> ()
| Error (e: string) ->
exn e |> raise
let endFlow<'a, 'T when 'T :> exn> (mkExn : string -> 'T) (x : Result<'a, string>) =
match x with
| Ok o -> ()
| Error (e: string) ->
mkExn e |> raise
let endFlow
let r : Result<int, string> = ...
r |> endFlow exn // throws System.Exception
r |> endFlow System.InvalidOperationException // throws System.InvalidOperationException