简体   繁体   English

F# TaskBuilder:如何在不返回虚拟值以符合编译器约束的情况下引发异常?

[英]F# TaskBuilder: how an exception can be raised without returning a dummy value to comply with compiler constraints?

In a F# TaskBuilder task , I'm trying to catch an exception and re-throw it as wrapped exception:在 F# TaskBuilder task ,我试图捕获异常并将其作为包装异常重新抛出:

open System.Threading.Tasks

open FSharp.Control.Tasks.V2


exception FakeDapperException of int

exception FakePersistenceException of string * exn


module FakeDapper =
    let executeWrongQueryAsync (sql: string) =
        task {
            raise (FakeDapperException(0))
            return 42
        }

module FakePersistenceLayer =
    let doSomeImportantDbRelatedStuffAsync (sql: string) =
        task {
            try
                return! FakeDapper.executeWrongQueryAsync sql
            with e ->
                FakePersistenceException(sql, e) |> raise
                return Unchecked.defaultof<int>
        }

module Task =
    let GetResult (task: Task<'T>) =
        task.GetAwaiter().GetResult()


[<EntryPoint>]
let main _ =
    let result =
        FakePersistenceLayer.doSomeImportantDbRelatedStuffAsync "this is some pretty sql stuff"
        |> Task.GetResult
    0

The code above works as expected, however, when I first implemented I wanted to have something like below:上面的代码按预期工作,但是,当我第一次实现时,我想要像下面这样:

let doSomeImportantDbRelatedStuffAsync (sql: string) =
    task {
        try
            return! FakeDapper.executeWrongQueryAsync sql
        with e ->
            FakePersistenceException(sql, e) |> raise
    }

which could not compile:无法编译:

Program.fs(23, 17): [FS0001] Type mismatch. Expecting a 'FSharp.Control.Tasks.TaskBuilder.Step<int>' but given a 'FSharp.Control.Tasks.TaskBuilder.Step<unit>'. 
The type 'int' does not match the type 'unit'

This is due to the way the task CE works, but I am wondering if there is a way to not return a useless value (ie return Unchecked.defaultof<int> ) to stop the compiler yelling at me.这是由于task CE 的工作方式造成的,但我想知道是否有办法不返回无用值(即return Unchecked.defaultof<int> )来阻止编译器对我大喊大叫。

The problem is that raise does not know what type to infer, due to being in the task CE.问题是raise不知道要推断什么类型,因为在task CE 中。 Because the first branch try has a return the last branch must have one as well (this return is where the type inference comes in)因为第一个分支try有一个return所以最后一个分支也必须有一个return值(这个return是类型推断出现的地方)

let doSomeImportantDbRelatedStuffAsync (sql: string) =
    task {
        try
            return! FakeDapper.executeWrongQueryAsync sql
        with e ->
            return FakePersistenceException(sql, e) |> raise
    }

This should make the type inference happy, as raise will infer the type of the task CE now.这应该使类型推断变得愉快,因为raise将推断task CE 的类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM