Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Casting and exception filters inside an F# `try`-`with` block

I'm trying to convert this piece of C# to F#:

var webClient = new WebClient();
try {
    webClient.DownloadString (url);
} catch (WebException e) {
    var response = e.Response as HttpWebResponse;
    if (response == null)
        throw;
    using (response) {
        using (Stream data = response.GetResponseStream ()) {
            string text = new StreamReader (data).ReadToEnd ();
            throw new Exception (response.StatusCode + ": " + text);
        }
    }
}

I've come up with this for now, but it doesn't compile because I cannot use let or use inside a with block apparently:

let Download(url: string) =
    use webClient = new WebClient ()
    try
        webClient.DownloadString(url)
    with
        | :? WebException as ex when ex.Response :? HttpWebResponse ->
             use response = ex.Response :?> HttpWebResponse
             use data = response.GetResponseStream()
             let text = new StreamReader (data).ReadToEnd ()
             failwith response.StatusCode + ": " + text
like image 904
knocte Avatar asked Mar 22 '23 01:03

knocte


1 Answers

A little bit of splitting things up and using parentheses would help you a lot here:

let download (url : string) = 
    use webClient = new WebClient()
    try
        webClient.DownloadString(url)
    with
        | :? WebException as ex when (ex.Response :? HttpWebResponse) ->
             use response = ex.Response :?> HttpWebResponse
             use data = response.GetResponseStream()
             use reader = new StreamReader(data)
             let text = reader.ReadToEnd()
             failwith (response.StatusCode.ToString() + ": " + text)

This function compiles and works as expected.

I'm not an expert, but if I had to guess I'd say that the expression after when has to be in brackets to enforce the correct order of evaluation (so type check first, then when it), not strictly left-to-right.

Same thing goes for failwith, for the string concatenation to be evaluated first it should be in brackets.

like image 65
Patryk Ćwiek Avatar answered Mar 31 '23 15:03

Patryk Ćwiek