I have a piece of code that is of the following form
let function arg1 arg2 =
match arg1 with
| type1 -> Some true
| type2 ->
async {
match! func2 arg3 arg4 with
| Result.Ok a -> return! Some true
| _ -> return! None
}
The problem here is that the func2 has to be used with match! statement and a normal match keyword is not able to compute the expression and thus I can not match pattern Some a. However, I can not use async in one of the branches alone.
Is there any method in F# that can convert Async<Result<a>> to Result<a> type ?
I am expecting a method such as Async.Evaluate that can perform computation and return a simple Result<a> object instead of a Async<Result<a>>. that would my code snippet look something like:
let function arg1 arg2 =
match arg1 with
| type1 -> Some true
| type2 ->
match (func2 arg3 arg4) |> Async.Evaluate with
| Result.Ok a -> Some true
| _ -> None
The function you're looking for is Async.RunSynchronously
match (func2 arg3 arg4) |> Async.RunSynchronously with
| Result.Ok a -> Some true
| _ -> None
Note, however, that, as a rule, a call to RunSynchronously should not appear anywhere in your code, except the entry point. Or maybe event handler, if you're working with a UI framework of some kind.
A better solution is to make the calling function also async:
let function arg1 arg2 =
match arg1 with
| type1 -> async { return Some true }
| type2 ->
async {
match! func2 arg3 arg4 with
| Result.Ok a -> return Some true
| _ -> return None
}
And then making the function calling it also async, and the one calling it, and the one calling it, and so on, all the way to the entry point, which would finally call RunSynchronously, or maybe even Async.Start, depending on your needs.
Related
I have a piece of code like this:
let! deliveries =
async {
match Option.map (fun x -> x.Address) maybeUser with
| Some "" -> return []
| Some address -> return! fetchDeliveries address
| None -> return []
}
The type inference on this fails at x.Address.
However, if I reorder the code with a pipe it works:
let! deliveries =
async {
match maybeUser |> Option.map (fun x -> x.Address) with
| Some "" -> return []
| Some address -> return! fetchDeliveries address
| None -> return []
}
Why is this?
This is because F#'s compiler is a single-pass, top-down, left-to-right compiler. So when typechecking a file, any type information from the left of an expression is able to be used to verify the right. The reason why the |> example works is because the left-hand side has a definite type (in this case some kind of User option type that you've defined, which tells Option.map that yes the item coming in is an User option, so the lambda function you pass in must be of type User -> something else, which of course it is.
I tried to implement this straight forward Maybe monad. So basically the whole expression evaluates to Nothing if one of the middle step is Nothing.
type Maybe<'a> =
| Just of 'a
| Nothing
type MaybeBuilder () =
member this.Combine ((first, second) : Maybe<'a> * Maybe<'b>) : Maybe<'b> =
printfn "Combine called"
match first with
| Nothing -> Nothing
| _ ->
match second with
| Nothing -> Nothing
| _ as a -> a
member this.Zero () = Just ()
member this.Bind((m, f) : Maybe<'a> * ('a -> Maybe<'b>)) =
printfn "Bind called"
match m with
| Nothing -> Nothing
| Just a -> f a
let MaybeMonad = MaybeBuilder()
let foobar =
MaybeMonad {
let! foo = Just "foo"
Just 1
Nothing
}
I expected foobar be translated into Just "foo" >>= fun foo -> Combine(Just 1, Nothing), however Combine wasn't called.
That's not the way the computation expression is expected to be written. Each time you want 'yield a result' you need to add some keyword (return, return!, yield or yield!) on the left side of the expression, in your example I would add a return!:
let foobar =
MaybeMonad {
let! foo = Just "foo"
return! Just 1
return! Nothing
}
But then you need to add its definition to the builder:
member this.ReturnFrom (expr) = expr
then the compiler will ask you to add a Delay method, in your case I think you're looking for something like:
member this.Delay(x) = x()
Almost there, now you have a value restriction, most likely because the Combine you defined doesn't use the same type on both arguments, you can either fix it or just add a type annotation in the return type:
let foobar : Maybe<int> =
MaybeMonad {
let! foo = Just "foo"
return! Just 1
return! Nothing
}
That's it, now you get:
Bind called
Combine called
printed and:
val foobar : Maybe<int> = Nothing
If you want to understand all the details of CEs have a look at this nice article: https://www.microsoft.com/en-us/research/publication/the-f-computation-expression-zoo/
I would like to do some unit tests on a function that accepts a DU and returns another :
type Commands =
| Schedule of string
| Abandon of string
type Events =
| Scheduled of string
| Abandonned of string
the function is the following :
let exec state = function
| Schedule (cmd) -> Choice1Of2( Scheduled("yes"))
| Abandon(cmd) -> Choice1Of2( Abandonned ("no"))
My tests are as follows :
let result:Choice<Events,string> = exec "initial state" <| Schedule("myCommand");;
result has the following type Choice<Events,string>, I would have loved to get some quick function in order to use them like this :
assertEvent Scheduled (fun e -> Assert.Equal("should produce GameScheduled Event",gameScheduled, e)) result
But to do that I would have the following home made assert function :
let assertEvent<'TEvent> f g result =
match result with
| Choice1Of2(e) ->
match e with
| f(evt) -> g(evt)
| _ -> Assert.None("event not recognised",Some(e))
| Choice2Of2(reason) -> Assert.None("reason",Some(reason))
I was expecting the function f to allow pattern matching on the fly but it does not. Instead I have the following error :
The pattern disciminator 'f' is not defined
Am I doing somthing wrong somewhere ? my fsharp skills are not that high...
A normal function like f can't be used as a pattern discriminator, but you can pass Active Patterns around as arguments:
let assertEvent<'TEvent> (|F|_|) g result =
match result with
| Choice1Of2(e) ->
match e with
| F(evt) -> g(evt)
| _ -> Assert.None("event not recognised",Some(e))
| Choice2Of2(reason) -> Assert.None("reason",Some(reason))
This does, however, require you to also pass an Active Pattern as an argument, which is a bit cumbersome:
assertEvent
(function Scheduled(x) -> Some x | _ -> None)
(fun e -> Assert.Equal("should produce GameScheduled Event",gameScheduled, e))
result
This isn't the way I'd approach the problem, though. What I'd prefer is to write a boolean expression that attempts to pull out and compare the values that I want to verify.
For starters, you could create a little generic helper function to pull out one of the choices from Choice<'a, 'b>:
let toOption1 = function Choice1Of2 x -> Some x | _ -> None
This function has the type Choice<'a,'b> -> 'a option. (I'll leave it as an exercise to define an equivalent toOption2 function.)
Now you can define a boolean expression that pulls out the data if it's there, and compares it with an expected value:
result
|> toOption1
|> Option.map (function Scheduled x -> x | _ -> "")
|> Option.exists ((=) expected)
This is a boolean expression, so you can use Unquote to turn it into an assertion. This is similar to this approach that I've previously described.
I understand that F# functions return a unit if nothing else is returned, but this function returns a string. Can someone please help me understand why it returns a unit?
let rec processList aList str =
match aList with
| h::t -> let x = Regex.Replace(str, h, h, RegexOptions.IgnoreCase)
processList t x
| [] -> printfn "%s" str
The stopping case for this recursive function
| [] -> printfn "%s" str
returns unit, and therefore the function returns a unit. The other branch only recursively call the same function.
If we analyse the two recursive branches, their return types must be identical.
The first branch has some return type 'a which is the return value of processList
The second branch returns unit as that is the return type of printfn. You probably want to have just
| [] -> str
or for a more complex case, you can use sprintf to return a formatted string as follows
| [] -> sprintfn "%s" str
What would be the most effective way to express the following code?
match cond.EvalBool() with
| true ->
match body.Eval() with
| :? ControlFlowModifier as e ->
match e with
| Break(scope) -> e :> obj //Break is a DU element of ControlFlowModifier
| _ -> next() //other members of CFM should call next()
| _ -> next() //all other values should call next()
| false -> null
cond.EvalBool returns a boolean result where false should return null
and true should either run the entire block again (its wrapped in a func called next)
or if the special value of break is found, then the loop should exit and return the break value.
Is there any way to compress that block of code to something smaller?
I think that the code that you have written is fine. Here's an alternative which I marginally prefer:
let isBreak = function | Break(_) -> true | _ -> false
if cond.EvalBool() then
match body.Eval() with
| :? ControlFlowModifier as e when isBreak e -> e :> obj
| _ -> next()
else
null
I want to point out that it appears there's a subtype hierarchy for the result type of Eval, and if instead that were also a DU, then you could do something like
match body.Eval() with
| ControlFlowModifier(Break e) -> box e
| _ -> next()
Hurray for nested patterns.
I'm not too fond of matching booleans instead of using if-else. What about
let isBreak = function Break _ -> true | _ -> false
...
if cond.EvalBool() then
match body.Eval() with
| :? ControlFlowModifier as e when isBreak e -> box e
| _ -> next()
else null
Or, if you think that special isBreak function shouldn't be necessary (I'd understand that), lets try creating a more general function: C#'s as operator
let tryCast<'T> (o : obj) =
match o with
| :? 'T as x -> Some x
| _ -> None
...
if cond.EvalBool() then
match body.Eval() |> tryCast with
| Some (Break _ as e) -> box e //Break is a DU element of ControlFlowModifier
| _ -> next() //all other values should call next()
else null
I ended up creating an active pattern for this.
Similar logic exist elsewhere so I could make it reusable
let rec next() : obj =
if cond.EvalBool() then
match body.Eval() with
| IsBreak(res) -> res
| _ -> step.Eval() |> ignore ; next()
else null
Looks decent?
To flatten the nested match constructs, you'll need to use nested patterns. This works best for discriminated unions (as pointed out by Brian - and I agree that designing F# code to use primarily discriminated unions is the best thing you can do).
Otherwise, you'll need some active patterns if you want to write the code succinctly using match (ssp posted one example, which shows active patterns specifically for your problem). However, you can do this using the following two reusable active patterns:
let (|TryCast|_|) a : 'res option =
match (box a) with
| :? 'res as r -> Some(r)
| _ -> None
let (|Value|) (l:Lazy<_>) = l.Value
The first one is like :?, but it allows you to nest other patterns to match the value (which isn't possible with as). The second one forces evaluation of lazy value (I suppose that both of them could be declared in F# libraries as they are quite useful). Now you can write:
match lazy cond.EvalBool(), lazy body.Eval() with
| Value(true), Value(TryCast((Break(scope) : ControlFlowModifier)) as e) ->
e :> obj //Break is a DU element of ControlFlowModifier
| Value(true), _ ->
next() //all other values should call next()
| _, _ -> null
EDIT: As Roger pointed out in a comment, this version of the code may not be very readable. I think a better option would be to use only TryCast and format your original code slightly differently (although this isn't completely standard indentation, it is correct and F# compiler handles it fine):
match cond.EvalBool() with
| false -> null
| true ->
match body.Eval() with
| TryCast(Break(scope) as e) -> e :> obj
| _ -> next()
This is probably the most readable option based on pattern matching, but you could also use if instad of the first match as in the version by kvb and combine it with TryCast (this really depends on personal preferences):
if cond.EvalBool() then
match body.Eval() with
| TryCast(Break(scope) as e) -> e :> obj
| _ -> next()
else null
In any case, I believe that TryCast makes the code more readable as you avoid one nesting (which is othervise required because of :? .. as ..).
In case you mean "most effective way" as shortest code, i vote to AP too:
let (|CondEval|_|) (c,_) = if c.EvalBool() then Some true else None
let (|BodyEval|_|) (_,b) =
match b.Eval() with
| ControlFlowModifier as e -> Some e
| _ -> None
match cond,body with
| CondEval _ & BodyEval e -> e :> obj
| true -> next()
| false -> null