How to declare a generic exception type in F#

后端 未结 2 1632
后悔当初
后悔当初 2021-01-12 01:52

How can I define an exception like the following?

exception CustomExn<\'TMessage> of \'TMessage list
相关标签:
2条回答
  • 2021-01-12 02:10

    Maybe you can just inherit from 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"
    
    0 讨论(0)
  • 2021-01-12 02:22

    Not sure it is possible with F# Exception Definitions according to specs (page 164-165)

    This one also NOT A GOOD SOLUTION because try with will only catch ExceptionList<string> in this case so there is no good way to make it generic

    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")
    

    The better way though: 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")
    

    Added There is a workaround with type loss:

    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")
    
    0 讨论(0)
提交回复
热议问题