Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to declare a generic exception type in F#

How can I define an exception like the following?

exception CustomExn<'TMessage> of 'TMessage list
like image 501
Mohsen Avatar asked Apr 23 '18 06:04

Mohsen


People also ask

How do you write a generic exception in Java?

A method is not allowed to catch an instance of a type parameter. public static <T extends Exception, J> void execute(List<J> jobs) { try { for (J job : jobs) {} // compile-time error //Cannot use the type parameter T in a catch block } catch (T e) { // ... } }

Can exception types be generic?

Since type parameters of generics are erased at runtime, there is no way to distinguish between generic exceptions with different type parameters in the catch clause, thus generic exceptions are not supported.

What are generic exceptions?

It refers to exception class that is near the top of the exception class hierarchy. Note that an exception class cannot be a generic class ... in the Java sense of generic types. The JLS says: "Note that a subclass of Throwable cannot be generic (§8.1.2)." -

What is a generic exception class?

In that context, the word "generic" is being used in the normal English sense: i.e. "not specific". It refers to exception class that is near the top of the exception class hierarchy. Note that an exception class cannot be a generic class ... in the Java sense of generic types. The JLS says:

How do I define and use F #exception types?

This topic describes how to define and use F# exception types. In the previous syntax, exception-type is the name of a new F# exception type, and argument-type represents the type of an argument that can be supplied when you raise an exception of this type. You can specify multiple arguments by using a tuple type for argument-type.

Can I throw a generic type in an exception in Java?

While exception are not allowed to contain generic type parameters it is perfectly fine to throw generic types (if they extend Throwable ). The following code compiles fine: .. However, it is not possible to use generic type parameters in catch blocks.

What is a generic function in F #?

F# - Generics. In F#, function values, methods, properties, and aggregate types such as classes, records, and discriminated unions can be generic. Generic constructs contain at least one type parameter. Generic functions and types enable you to write code that works with a variety of types without repeating the code for each type.


2 Answers

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"
like image 147
3615 Avatar answered Oct 21 '22 15:10

3615


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")
like image 24
Szer Avatar answered Oct 21 '22 16:10

Szer