如何在F#中使用类型测试模式匹配异常?

问题描述

我有一个功能,需要在以下代码段中使用类型test pattern match (不是try...with例外

module Error =

    type Codes =
        | InvalidUser = 0
        | InvalidEmail = 1

    exception AppException of Codes

    let errorHandler (e: exn) =
        // This doesn't work
        match e with
        | :? AppException as err(code) ->
            code.ToString()
        | _ -> e.Message

errorHandler一个通用函数,用于捕获应用程序中的AppExeption以及其他未处理的异常。

如何将模式匹配与类型测试结合使用,并在code中解构/检索AppException

解决方法

要达到最终要完成的目标,我将在此处进行两项更改:

  1. Codes从枚举更改为DU
  2. 删除类型测试,因为对于F#定义的异常而言并不必要

它可能看起来像这样:

open System

module Error =

    type Codes =
        | InvalidUser
        | InvalidEmail

    exception AppException of Codes

    let errorHandler (e: exn) =
        match e with
        | AppException codes ->
            match codes with
            | InvalidUser -> "invalid users!"
            | InvalidEmail -> "invalid email!"
        | _ -> e.Message

或者,如果嵌套模式匹配使您不满意,在这种情况下,您可以将其展平:

let errorHandler (e: exn) =
    match e with
    | AppException InvalidUser ->
        "invalid user!"
    | AppException InvalidEmail ->
        "invalid email"
    | _ -> e.Message

F#定义的例外是有效的区分大小写的联合,可以直接在其上进行模式匹配。这里没有类型测试。

如果Codes必须保留为枚举,您仍然可以执行第一个代码示例,但是您需要在内部match表达式中使用全包式,因为枚举只是int下的封面。

let errorHandler (e: exn) =
    // This doesn't work
    match e with
    | AppException codes ->
        match codes with
        | Codes.InvalidUser -> "invalid users!"
        | Codes.InvalidEmail -> "invalid email!"
        | _ -> "something else?"
    | _ -> e.Message