I think this will be simple but I've spent the past hour trying everything I can think of and researching online to no avail.
(I'm new to F#)
I have the following code which sends a HTTP Request, it then matches the result. If it doesn't match anything ( | _ ) I want to just print its string value to console. How would I go about doing this?
match Http.RequestString("http://foo.com/res.php",
httpMethod = "GET",
query = ["key", key; "action", "get"; "id", id]) with
| "CAPCHA_NOT_READY" -> printfn "Sleeping for 5"
Thread.Sleep(5000)
GetCaptchaRequest id
| _ -> printfn ???
The underscore character is used when you don't care about the value and won't be using it in subsequent code. You just need to give the variable a name. Try this:
| msg -> printfn "%s" msg
In this example, I've chosen msg as the variable name but it can be any valid variable name you choose.
Since all the branches of a match statement must return the same type, you will need more than just the printfn statement. In cases like this, where the external call could potentially fail, it is a common idiom to use the Option<'a> type to represent success or failure.
Not knowing the specifics of your API endpoint, consider this pseudocode:
let GetCaptchaRequest id : string option =
match Http.RequestString("http://foo.com/res.php",
httpMethod = "GET",
query = ["key", key; "action", "get"; "id", id]) with
| "CAPCHA_NOT_READY" -> printfn "Sleeping for 5"
Thread.Sleep(5000)
GetCaptchaRequest id
| "ERROR" -> printfn "Something went wrong!"
None
| result -> printfn "Successful result!"
Some (parseMyCaptchaResult result)
Related
How do I retrieve a value from a generic?
Specifically, I am attempting the following:
// Test
let result = Validate goodInput;;
// How to access record??
let request = getRequest result
Here's the code:
type Result<'TSuccess,'TFailure> =
| Success of 'TSuccess
| Failure of 'TFailure
let bind nextFunction lastFunctionResult =
match lastFunctionResult with
| Success input -> nextFunction input
| Failure f -> Failure f
type Request = {name:string; email:string}
let validate1 input =
if input.name = "" then Failure "Name must not be blank"
else Success input
let validate2 input =
if input.name.Length > 50 then Failure "Name must not be longer than 50 chars"
else Success input
let validate3 input =
if input.email = "" then Failure "Email must not be blank"
else Success input;;
let Validate =
validate1
>> bind validate2
>> bind validate3;;
// Setup
let goodInput = {name="Alice"; email="abc#abc.com"}
let badInput = {name=""; email="abc#abc.com"};;
// I have no clue how to do this...
let getRequest = function
| "Alice", "abc#abc.com" -> {name="Scott"; email="xyz#xyz.com"}
| _ -> {name="none"; email="none"}
// Test
let result = Validate goodInput;;
// How to access record??
let request = getRequest result
printfn "%A" result
You mean how do you extract the record out of your result type? Through pattern matching, that's what you're already doing in bind.
let getRequest result =
match result with
| Success input -> input
| Failure msg -> failwithf "Invalid input: %s" msg
let result = Validate goodInput
let record = getRequest result
This will return the record or throw an exception. Up to you how you handle the success and failure cases once you have your Result - that could be throwing an exception, or turning it into option, or logging the message and returning a default etc.
This seems to be a frequently asked question: How do I get the value out of a monadic value? The correct answer, I believe, is Mu.
The monadic value is the value.
It's like asking, how do I get the value out of a list of integers, like [1;3;3;7]?
You don't; the list is the value.
Perhaps, then, you'd argue that lists aren't Discriminated Unions; they have no mutually exclusive cases, like the above Result<'TSuccess,'TFailure>. Consider, instead, a tree:
type Tree<'a> = Node of Tree<'a> list | Leaf of 'a
This is another Discriminated Union. Examples include:
let t1 = Leaf 42
let t2 = Node [Node []; Node[Leaf 1; Leaf 3]; Node[Leaf 3; Leaf 7]]
How do you get the value out of a tree? You don't; the tree is the value.
Like 'a option in F#, the above Result<'TSuccess,'TFailure> type (really, it's the Either monad) is deceptive, because it seems like there should only be one value: the success. The failure we don't like to think about (just like we don't like to think about None).
The type, however, doesn't work like that. The failure case is just as important as the success case. The Either monad is often used to model error handling, and the entire point of it is to have a type-safe way to deal with errors, instead of exceptions, which are nothing more than specialised, non-deterministic GOTO blocks.
This is the reason the Result<'TSuccess,'TFailure> type comes with bind, map, and lots of other goodies.
A monadic type is what Scott Wlaschin calls an 'elevated world'. While you work with the type, you're not supposed to pull data out of that world. Rather, you're supposed to elevate data and functions up to that world.
Going back to the above code, imagine that given a valid Request value, you'd like to send an email to that address. Therefore, you write the following (impure) function:
let send { name = name; email = email } =
// Send email using name and email
This function has the type Request -> unit. Notice that it's not elevated into the Either world. Still, you want to send the email if the request was valid, so you elevate the send method up to the Either world:
let map f = bind (fun x -> Success (f x))
let run = validate1 >> bind validate2 >> bind validate3 >> map send
The run function has the type Request -> Result<unit,string>, so used with goodInput and badInput, the results are the following:
> run goodInput;;
val it : Result<unit,string> = Success unit
> run badInput;;
val it : Result<unit,string> = Failure "Name must not be blank"
And then you probably ask: and how do I get the value out of that?
The answer to that question depends entirely on what you want to do with the value, but, imagine that you want to report the result of run back to the user. Displaying something to the user often involves some text, and you can easily convert a result to a string:
let reportOnRun = function
| Success () -> "Email was sent."
| Failure msg -> msg
This function has the type Result<unit,string> -> string, so you can use it to report on any result:
> run goodInput |> reportOnRun;;
val it : string = "Email was sent."
> run badInput |> reportOnRun;;
val it : string = "Name must not be blank"
In all cases, you get back a string that you can display to the user.
I need help understanding the concepts behind the following:
I have this:
type Result<'TSuccess,'TFailure> =
| Success of 'TSuccess
| Failure of 'TFailure
But this doesn't work:
let getRequest = function
| Success input -> input
| Failure msg -> msg
But this does:
let getRequest result =
match result with
| Success input -> input
| Failure msg -> failwithf "Invalid input: %s" msg
Why does the initial "getRequest" fail?
Again, I just don't understand the basic rules for pattern matching.
Can someone please shed some light on this?
The entire code is here:
module Core
type Result<'TSuccess,'TFailure> =
| Success of 'TSuccess
| Failure of 'TFailure
let bind nextFunction lastFunctionResult =
match lastFunctionResult with
| Success input -> nextFunction input
| Failure f -> Failure f
type Request = {Name:string; Email:string}
let validate1 input =
if input.Name = "" then Failure "Name must not be blank"
else Success input
let validate2 input =
if input.Name.Length > 50 then Failure "Name must not be longer than 50 chars"
else Success input
let validate3 input =
if input.Email = "" then Failure "Email must not be blank"
else Success input;;
let Validate =
validate1
>> bind validate2
>> bind validate3;;
// Setup
let goodInput = {Name="Alice"; Email="abc#abc.com"}
let badInput = {Name=""; Email="abc#abc.com"};;
let getRequest = function
| Success input -> input
| Failure msg -> msg
// Test
let result = Validate goodInput;;
let request = getRequest result;;
Given this definition
let getRequest = function
| Success input -> input
| Failure msg -> msg
we can reason about its type as follows:
Since it's a function, it has type ?1 -> ?2 for some not-yet-known placeholder types.
The input uses the Success and Failure union cases, so the input must itself actually be some type Result<?3,?4>, and the function's type is Result<?3,?4> -> ?2.
The types of each branch must be the same as the function's return type.
Looking at the first branch, we see this means that ?3 = ?2.
Looking at the second branch, this means that ?4 = ?2.
Therefore the overall type of the function must be Result<?2,?2> -> ?2, or using real F# notation, Result<'a,'a> -> 'a where 'a can be any type - this is a generic function definition.
But Validate has type Request -> Result<Request, string>, so its output isn't consistent with this definition of getResult because the success and failure types are different and you can't just directly pass the results from one to the other.
On the other hand, with
let getRequest = function
| Success input -> input
| Failure msg -> failwithf "Invalid input: %s" msg
we would analyze it like this:
As before, any function has type ?1 -> ?2.
As before, the input must clearly be a Result<?3,?4>.
But analyzing the branches, we get a different result:
The first branch again leads to the constraint ?3 = ?2.
But the second branch is different - failwithf with that format pattern takes a string and throws an exception (and can have any return type, since it never returns normally), so we see msg must be a string, so ?4 = string.
So the overall type is Result<'a,string> -> 'a, which now allows you to pass a Result<Request,string> to it, as desired.
I think your question actually gives a good platform to explain pattern matching.
Let's start by thinking about the types involved, your getRequest function must be a function with some type signature getRequest : 'a -> 'b', i.e. it takes something of one type and returns something of another but let's look at what you've written.
let getRequest =
function
| Success input -> input // this branch would return 'TSuccess
| Failure msg -> msg // this brach would return 'TFailure
You can't have a function whose type signature is 'a -> 'b or 'c. (The only way to make this function compile is if 'b and 'c can be constrained to be the same type, then we do simply have a consistent 'a -> 'b).
But wait, enter the discriminated union.
Your discriminated union has type Result<'TSuccess,'TFailure>. Or, to describe things as I did above type 'd<'b,'c>. Now, we absolutely can have a function whose type signature is 'a -> 'd<'b,'c>.
'd<'b, 'c> is just a generic type which involves 'b and it involves 'c. The type signature includes all of these things, so hopefully you can see that we can contain both a 'TSuccess and 'TFailure in this type with no problem.
So, if we want to return something which can contain different combinations of types, we've found the perfect use case for the discriminated union. It can contain the 'TSuccess or the 'TFailure in one type. You can then choose between those results using pattern matching.
let getRequest =
function
| Success input -> printfn "%A" input // do something with success case
| Failure msg -> printfn "%A" msg // do something with failure case
So long as we have consistent return types in each case, we can insert any behaviour we want.
On to the next point of why throwing an exception is okay. Let's look at the type signature of the failwithf function: failwithf : StringFormat<'T,'Result> -> 'T. The failwithf function takes a string format and returns some type 'T.
So let's look at your second function again
let getRequest result =
match result with
| Success input -> input // type 'TSuccess
| Failure msg -> failwithf "Invalid input: %s" msg // type 'T inferred to be 'TSuccess
The function signature is consistent, 'a -> 'TSuccess.
The following works as I would expect.
type Result =
| Success
| Failure
type Response =
| Result of Result
let response = Response.Result <| Result.Success
match response with
| Result result ->
match result with
| Result.Success -> printfn "Success"
| Result.Failure -> printfn "Failure"
However, when I place some of it in a module:
module Module =
type Result =
| Success
| Failure
type Response =
| Result of Result
let response = Module.Response.Result <| Module.Result.Success // <- ERROR HERE
I get the error:
The field, constructor or member 'Success' is not defined
And it also means that I can't do matching like:
match response with
| Module.Result result ->
match result with
| Module.Result.Success -> printfn "Success"
| Module.Result.Failure -> printfn "Failure"
which fails with
This is not a constructor or literal, or a constructor is being used incorrectly
(To get this to fail, some additional code needs to be added such that Module has a createResponse:
let createResponse b =
if b
then Response.Result <| Result.Success
else Response.Result <| Result.Failure
and response in the code outside the module is then let response = Module.createResponse true.
Shouldn't I be able to achieve the same result regardless of putting some code in a module?
Actually fully qualified name Module.Result.Success should work where first error happens. Compiler confusion comes because you gave the same name to two different things.
This line will compile:
let response = Module.Response.Result <| Module.Success
And you can do pattern matching this way:
match response with
| Module.Result result ->
match result with
| Module.Success -> printfn "Success"
| Module.Failure -> printfn "Failure"
In the last example: you are matching response value against Module.Result with parameter result. It could be only of type Module.Response because the single case of this type - namely Module.Result - has a parameter. And because this parameter is of type Module.Result it could be matched against two cases of this type: Module.Success and Module.Failure. It looks and sound confusing because it is. The same name "Result" is given both to discriminated union type and to the case-id of another discriminate union type. I would change Response type to something like this:
type Response =
| RespResult of Result
I have the following code which will return a seq of DownloadLink for these Urls that can be parsed.
type DownloadLink = { Url: string; Period: DateTime }
nodes |> Seq.map (fun n ->
let url = n.Attributes.["href"].Value
match url with
| Helper.ParseRegex "[a-zA-Z](?<period>\d{4})\.txt" [period] ->
{ Url = url; Period = period }
| _ ->
printfn "Cannot parse %s" url // Error
)
However, I got the following error at the printfn. What's right way to implement it? Should I make it a list option first and then filter out these None items?
Error 1 Type mismatch. Expecting a
string -> DownloadLink
but given a
string -> unit
The type 'DownloadLink' does not match the type 'unit'
The basic problem is that if you have something like
match x with
|true -> A
|false -> B
the type of A and B must be the same.
There is actually a build in function that combines the map and filter using Some that you had though of - use Seq.choose like so
nodes |> Seq.choose (fun n ->
let url = n.Attributes.["href"].Value
match url with
| Helper.ParseRegex "[a-zA-Z](?<period>\d{4})\.txt" [period] ->
Some ({ Url = url; Period = period })
| _ ->
printfn "Cannot parse %s" url // Error
None
)
Aside from Seq.choose, you can also nicely solve the problem using sequence expressions - where you can use yield to return result in one branch, but do not have to produce a value in another branch:
seq { for n in nodes do
let url = n.Attributes.["href"].Value
match url with
| Helper.ParseRegex "[a-zA-Z](?<period>\d{4})\.txt" [period] ->
yield { Url = url; Period = period }
| _ ->
printfn "Cannot parse %s" url }
Aside, I would not recommend doing a side effect (printing) as part of your processing code. If you want to report errors, it might be better to return an option (or define a type which is either Success or Error of string) so that the error reporting is separated from processing.
I want to make something like it (Nemerle syntax)
def something =
match(STT)
| 1 with st= "Summ"
| 2 with st= "AVG" =>
$"$st : $(summbycol(counter,STT))"
on F# so is it real with F#?
There is no direct support for that but you can mimic the effect like this as well:
let 1, st, _ | 2, _, st = stt, "Summ", "AVG"
sprintf "%s %a" st summbycol (counter, stt)
If I understand you correctly, you'd like to assign some value to a variable as part of the pattern. There is no direct support for this in F#, but you can define a parameterized active pattern that does that:
let (|Let|) v e = (v, e)
match stt with
| Let "Summ" (st, 1)
| Let "AVG" (st, 2) -> srintf "%s ..." st
The string after Let is a parameter of the pattern (and is passed in as value of v). The pattern then returns a tuple containing the bound value and the original value (so you can match the original value in the second parameter of the tuple.