如何在F#中声明一般的异常类型

时间:2018-04-23 06:33:09

标签: generics exception f#

如何定义如下的异常?

exception CustomExn<'TMessage> of 'TMessage list

2 个答案:

答案 0 :(得分:4)

也许你可以继承System.Exception?

type CustomExn<'TMessage> (message:'TMessage list) =
    inherit System.Exception ()  

let test =
    try
        raise (CustomExn["string"] )
    with 
    | :? CustomExn<string> -> "CustomExn of string"
    | :? CustomExn<int> -> "CustomExn of int"
    | _ ->  "Everything else"

答案 1 :(得分:4)

根据specs(第164-165页)不确定是否可以使用F#Exception Definitions

这个不是一个好的解决方案,因为在这种情况下try with只能抓住ExceptionList<string>因此没有好办法让它变得通用

type ExceptionList<'a>(msgList: 'a list) =
    inherit Exception()
    member __.MessageList = msgList

let mock() = 
    raise <| ExceptionList(["failed"])

try
    mock() //raises ExceptionList<string>
with
    //this catch block won't fire, because it is not generic, it is ExceptionList<obj>
    | :? ExceptionList<_> as exnList -> 
        exnList.MessageList 
        |> List.iter (printfn "%A")

更好的方法:Result<'a,'b list>

let mock'() = 
    if DateTime.Now.Ticks % 2L = 0L 
    then Ok()
    else Error(["failed"])

let result = mock'()
match result with
| Ok _ -> printfn "Ok!"
| Error (msgList) -> 
      msgList
      |> List.iter (printfn "%A")

已添加有一种类型丢失的解决方法:

type ExceptionList(msgList: obj list) =
    inherit Exception()
    member __.MessageList = msgList

// Here is F# exception definition
exception CustomException of ExceptionList

let failwithMany msgs = 
    raise <| CustomException (ExceptionList(msgs))

let mock() =
    //zero type checking here
    failwithMany[1;2;"a";[];"failed"]

try
    mock()
with
    // exnList is list of objects
    | CustomException exnList ->
        exnList.MessageList 
        |> List.iter (printfn "%A")