I' working on a basic 2D CAD engine and the pipeline operator significantly improved my code. Basically several functions start with a point (x,y) in space and compute a final position after a number of move operations:
let finalPosition =
startingPosition
|> moveByLengthAndAngle x1 a1
|> moveByXandY x2 y2
|> moveByXandAngle x3 a3
|> moveByLengthAndAngle x4 a4
// etc...
This is incredibly easy to read and I'd like to keep it that way. The various x1, a1, etc. obviously have a meaning name in the real code.
Now the new requirement is to introduce exception handling. A big try/with around the whole operation chain is not enough because I'd like to know which line caused the exception. I need to know which argument is invalid, so that the user knows what parameter must be changed.
For example if the first line (moveByLengthAndAngle x1 a1) raises an exception, I'd like to tell something like "Hey, -90 is an invalid value for a1! a1 must be between 45 and 90!". Given that many operations of the same type can be used in the sequence it's not enough to define a different exception type for each operation (in this example I wouldn't be able to tell if the error was the first or the last move).
The obvious solution would be to split the chain in single let statements, each within its respective try/with. This however would make my beautiful and readable code a bit messy, not so readable anymore.
Is there a way to satisfy this requirement without sacrificing the readability and elegance of the current code?
(note. right now every moveBy function raises an exception in case of errors, but I'm free to change for ex. to return an option, a bigger tuple, or just anything else if needed).
The solution that Rick described is only going to handle exceptions that are raised when evaluating the arguments of the functions in the pipeline. However, it will not handle the exceptions that are raised by the pipelined functions (as described in answer to your other question).
For example, let's say you have these simple functions:
let times2 n = n * 2
let plus a b = a + b
let fail n = failwith "inside fail"
10 // This will handle exception that happens when evaluating arguments
|> try plus (failwith "evaluating args") with _ -> 0
|> times2
|> try fail with _ -> 0 // This will not handle the exception from 'fail'!
To solve this, you can write a function that wraps any other function in an exception handler. The idea that your protect function will take a function (such as times2 or fail) and will return a new function that takes the input from the pipeline (number) and passes it to the function (times2 or fail), but will do this inside exception handler:
let protect msg f =
fun n ->
try
f n
with _ ->
// Report error and return 0 to the pipeline (do something smarter here!)
printfn "Error %s" msg
0
Now you can protect each function in the pipeline and it will also handle exceptions that happen when evaluating these functions:
let n =
10 |> protect "Times" times2
|> protect "Fail" fail
|> protect "Plus" (plus 5)
How about folding over Choices? Let's say that instead of pipelining the actions, you represent them like this:
let startingPosition = 0. ,0.
let moveByLengthAndAngle l a (x,y) = x,y // too lazy to do the math
let moveByXandY dx dy (x,y) =
//failwith "oops"
x+dx, y+dy
let moveByXandAngle dx a (x,y) = x+dx, y
let actions =
[
moveByLengthAndAngle 0. 0., "failed first moveByLengthAndAngle"
moveByXandY 1. 2., "failed moveByXandY"
moveByXandY 3. 4., "failed moveByXandY"
moveByXandAngle 3. 4., "failed moveByXandAngle"
moveByLengthAndAngle 4. 5., "failed second moveByLengthAndAngle"
]
i.e. actions is of type ((float * float -> float * float) * string) list.
Now, using FSharpx we lift the actions to Choice and fold/bind (not sure how to call it this is similar to foldM in Haskell) over the actions:
let folder position (f,message) =
Choice.bind (Choice.protect f >> Choice.mapSecond (konst message)) position
let finalPosition = List.fold folder (Choice1Of2 startingPosition) actions
finalPosition is of type Choice<float * float, string> , i.e. it's either the final result of all those functions, or an error (as defined in the table above).
Explanation for this last snippet:
Choice.protect is similar to Tomas' protect, except that when it finds an exception, it returns the exception wrapped in a Choice2Of2. When there's no exception, it returns the result wrapped in a Choice1Of2.
Choice.mapSecond changes this potential exception in Choice2Of2 with the error message defined in the table of actions. Instead of (konst message) this could also be a function that builds the error message using the exception.
Choice.bind runs this "protected" action against the current position. It will not run the actual action if the current position is in error (i.e. a Choice2Of2).
Finally, the fold applies all actions threading along / accumulating the resulting Choice (either the current position or an error).
So now we just have to pattern match to handle each case (correct result or error):
match finalPosition with
| Choice1Of2 (x,y) ->
printfn "final position: %f,%f" x y
| Choice2Of2 error ->
printfn "error: %s" error
If you uncomment failwith "oops" above, finalPosition will be a Choice2Of2 "failed moveByXandY"
There's a lot of ways to approach this, the easiest would be to just wrap each call in a try-with block:
let finalPosition =
startingPosition
|> (fun p -> try moveByLengthAndAngle x1 a1 p with ex -> failwith "failed moveByLengthAndAngle")
|> (fun p -> try moveByXandY x2 y2 p with ex -> failwith "failed moveByXandY")
|> (fun p -> try moveByXandAngle x3 a3 p with ex -> failwith "failed moveByXandAngle")
|> (fun p -> try moveByLengthAndAngle x4 a4 p with ex -> failwith "failed moveByLengthAndAngle")
// etc...
Behold the power of expression oriented programming :).
Unfortunately, if you're pipelining over a sequence it becomes much more difficult as:
What happens in the pipeline (for Seqs) is composition, not execution.
Exception handling inside an IEnumerable is undefined and so depends on the implementation of the Enumerator.
The only safe way is to make sure the internals of each sequence operation are wrapped.
Edit: Wow, I can't believe I messed that up. It's fixed now but I do think that the two other solutions are cleaner.
I am unclear why
Now the new requirement is to introduce exception handling. A big
try/with around the whole operation chain is not enough because I'd
like to know which line caused the exception. I need to know which
argument is invalid, so that the user knows what parameter must be
changed.
the debugger isn't sufficient for this. This sounds like a design-time bug in the user's code; each of these methods might throw ArgumentException and nothing would handle it (it would crash the app), and the programmer would debug and see the method/stack that threw the exception, and the exception text would have the argument name.
(Or maybe this is FSI/scripting typically?)
Why not just put the exception handling in the function calls and throw them. Wouldn't this break the code. Then in your function that calls this, catch the error and display to user.
Related
It is actually pretty unxpected to me but consider this snippet in F#:
let f x =
printfn $"{x}"
fun x' -> x'
let y<'t> = f 1 //> val y<'t> : (obj -> obj)
y 2
//>
//1
//val it: obj = 2
what I would expect is that it will print "1" only when you bind f 1 to "y" (and that would tell me that "f" body only executes once) but seem like it executes "f" body on the every call of "y". Is it unavoidable effect related to auto curring or I'm missing something and there is a way to bypass outer function body execution on the every call of the returned function?
The hint as to what's going on here is the fact that 't has been constrained to obj and the signature of y is (obj -> obj). That's the F# compiler effectively say, "I give up, these have no real types, it is whatever it is" and emitting something that can execute at runtime but without any real type safety.
A side effect of this is that because it can't "pin down" y to a known signature, it cannot evaluate f, so it just emits y as a direct call to f, since you've effectively told the compiler that this is fine by parameterizing it with 't (which ends up just being obj, or "whatever").
Why is this happening? Value restriction!
I suspect you've evaluated this in F# Interactive block-by-block. The line of code that defines let y = f 1 is not possible to compile with more information. You can do so in two ways:
Use y with a real type that will pin its signature to the type you're using it as.
Give it an explicit signature like let y: int -> int = f 1 so that it's pinned down to a concrete type.
That's why if you execute this entire snippet in FSI or run it as a program, things work exactly like you'd expect:
let f x =
printfn $"{x}"
fun x' -> x'
let y = f 1
y 2
y 3
This is because y is generic.
Every time you refer to y, you choose a particular 't to go with that. For example:
let a = y<int>
let b = y<string>
a and b cannot be the same value, because they have been obtained from different instantiations of y. They have to be two different values. And this in turn means that y itself cannot be a single value. It has to be a function.
And that's what it is under the hood: it's compiled as a function, and every time you refer to it, the function is instantiated with the generic parameter you chose, and the body of the function is executed to obtain the result.
If you remove the generic parameter and give y a concrete type, the issue should go away:
let y = f 1 : obj -> obj
I have some code which I'm expecting to pause when it asks for user input. It only does this however, if the last expression is Seq.initInfinite.
let consoleaction (i : int) =
Console.WriteLine ("Enter Input: ")
(Console.ReadLine().Trim(), i)
Seq.initInfinite (fun i -> consoleaction i) |> Seq.map (fun f -> printfn "%A" f)
printfn "foo" // program will not pause unless this line is commented out.
Very new to F# and I've spent way too much time on this already. Would like to know what is going on :)
If you try that piece of code in F# interactive you will see different effects depending on how you execute it.
For instance if you execute it in one shot it will create values but nothing will be executed since the Seq.initInfinite instruction is 'lost' I mean, not let-bound to anything and at the same time is a lazy expression so its side effects will not be executed. If you remove the last instruction it will start prompting, that's because fsi bounds to it the last expression so in order to show you the value of it it starts evaluating the seq expression.
Things are different if you put this in a function, for example:
open System
let myProgram() =
let consoleaction ...
Now you will get a warning on the Seq.initInfinite:
warning FS0020: This expression should have type 'unit', but has type
'seq<unit>'. Use 'ignore' to discard the result of the expression, or
'let' to bind the result to a name.
Which is very clear. Additionally to ignore as the warning suggest you can change the Seq.map to Seq.iter since you are not interested in the result of the map which will be a seq of units.
But now again your program will not execute (try myProgram())unless you remove the last line, the printfn and it's clear why, this is because it returns the last expression which is not the Seq.initInfinite which is lost since it's lazy and ignored.
If you remove the printfn it will become the 'return value' of your function so it will be evaluated when calling the function.
In functional languages (using F#), I am struggling to find a balance between the advantages of functional composition with single-responsibility and getting the performance of single iteration over sequences. Any code pattern suggestions / examples for achieving both?
I don't have a solid background in computational theory and I run into this general pattern over and over: Iterating over a collection and wanting to do side-effects while iterating to avoid further iterations over the same collection or its result set.
A typical example is a "reduce" or "filter" function: There are many times while filtering that I want to take an additional step based on the filter's result, but I'd like to avoid a second enumeration of the filtered results.
Let's take input validation as a simple problem statement:
Named input array
Piped to an "isValid" function filter
Side-effect: Log invalid input names
Pipe valid inputs to further execution
Problem Example
In F#, I might initially write:
inputs
// how to log invalid or other side-effects without messing up isValid??
|> Seq.filter isValid
|> execution
Solution Example #1
With an in-line side-effect, I need something like:
inputs
|> Seq.filter (fun (name,value) ->
let valid = isValid (name,value)
// side-effect
if not valid then
printfn "Invalid argument %s" name
valid
|> execution
Solution Example #2
I could use tuples to do a more pure separation of concerns, but requiring a second iteration:
let validationResults =
inputs
// initial iteration
|> Seq.filter (fun (name,value) ->
let valid = isValid (name,value)
(name,value,valid)
|> execution
// one example of a 2nd iteration...
validationResults
|> Seq.filter (fun (_,_,valid) -> not valid)
|> Seq.map (fun (name,_,_) -> printfn "Invalid argument %s" name)
|> ignore
// another example of a 2nd iteration...
for validationResult in validationResults do
if not valid then
printfn "Invalid argument %s" name
Update 2014-07-23 per Answer
I used this as the solution per the answer. The pattern was to use an aggregate function containing the conditional. There are probably even more elegantly concise ways to express this...
open System
let inputs = [("name","my name");("number","123456");("invalid","")]
let isValidValue (name,value) =
not (String.IsNullOrWhiteSpace(value))
let logInvalidArg (name,value) =
printfn "Invalid argument %s" name
let execution (name,value) =
printfn "Valid argument %s: %s" name value
let inputPipeline input =
match isValidValue input with
| true -> execution input
| false -> logInvalidArg input
inputs |> Seq.iter inputPipeline
Following up on my other answer regarding composition of logging and other side-effects in F#, in this example, you can write a higher-level function for logging, like this:
let log f (name, value) =
let valid = f (name, value)
if not valid then
printfn "Invalid argument %s" name
valid
It has this signature:
f:(string * 'a -> bool) -> name:string * value:'a -> bool
So you can now compose it with the 'real' isValid function like this:
inputs
|> Seq.filter (log isValid)
|> execution
Since the isValid function has the signature name:'a * value:int -> bool it fits the f argument for the log function, and you can partially apply the log function as above.
This doesn't address your concern of iterating the sequence only once (which, for an array, is very cheap anyway), but is, I think, easier to read and clearer:
let valid, invalid = Array.partition isValid inputs
for name, _ in invalid do printfn "Invalid argument %s" name
execution valid
I'm trying to learn F# by going through some of the Euler problems and I found an issue I haven't been able to figure out. This is my naive solution.
let compute =
let mutable f = false
let mutable nr = 0
while f = false do
nr <- nr + 20
f = checkMod nr
nr
When i do this I get the error message warning FS0020: This expression should have type 'unit', but has type 'bool' on the expression "nr <- nr +20". I've tried rewriting and moving the expressions around and I always get that error on the line below the while statement.
I'm writing this using VS2010 Beta.
Since I can imagine this weg page becoming the 'canonical' place to look up information about warning FS0020, here's my quick summary of the three commonest cases in which you get the warning, and how to fix them.
Intentionally discarding the result of a function that is called only for its side-effects:
// you are calling a function for its side-effects, intend to ignore result
let Example1Orig() =
let sb = new System.Text.StringBuilder()
sb.Append("hi") // warning FS0020
sb.Append(" there") // warning FS0020
sb.ToString()
let Example1Fixed() =
let sb = new System.Text.StringBuilder()
sb.Append("hi") |> ignore
sb.Append(" there") |> ignore
sb.ToString()
Warning is useful, pointing out an error (function has no effects):
// the warning is telling you useful info
// (e.g. function does not have an effect, rather returns a value)
let Example2Orig() =
let l = [1;2;3]
List.map (fun x -> x * 2) l // warning FS0020
printfn "doubled list is %A" l
let Example2Fixed() =
let l = [1;2;3]
let result = List.map (fun x -> x * 2) l
printfn "doubled list is %A" result
Confusing assignment operator and equality comparison operator:
// '=' versus '<-'
let Example3Orig() =
let mutable x = 3
x = x + 1 // warning FS0020
printfn "%d" x
let Example3Fixed() =
let mutable x = 3
x <- x + 1
printfn "%d" x
The following line:
f = checkMod nr
is an equality check, not an assignment as I believe you are intending. Change it to:
f <- checkMod nr
and all should work fine. I'm not sure why you've used the correct syntax on the previous line and not that line...
Also, the line while f = false do should really be simplified to while not f do; equality checks on booleans are rather convoluted.
As I side note, I feel a need to point out that you are effectively trying to use F# as an imperative language. Use of mutable variables and while loops are strongly discouraged in functional languages (including F#), especially when a purely functional (and simpler) solution exists, as in this situation. I recommend you read up a bit on programming in the functional style. Of course, just getting to grips with the syntax is a useful thing in itself.
If you're trying to adopt the functional style, try to avoid mutable values.
For example like this:
let nr =
let rec compute nr =
if checkMod nr then nr else compute (nr + 20)
compute 0
while expressions in F# take a little getting used to if you're coming from an imperative language. Each line in a while expression must evaluate to unit (think void from C++/C#). The overall expression then also evaluates to unit.
In the example:
nr <- nr + 20
evaluates to unit whereas
f = checkMod nr
evaluates to a bool as Noldorin noted. This results in a warning message being reported. You can actually turn the warning off if you so desire. Just put the following at the top of your file:
#nowarn "0020"
I've been programming in an imperative style for a long time, so getting used to the functional programming mindset took a while.
In your example, you're trying to find the first multiple of 20 that passes your checkMod test. That's the what part. For the functional how part, I recommend browsing through the methods available to sequences. What you need is the first element of a sequence (multiples of 20) passing your test, like this:
let multi20 = Seq.initInfinite (fun i -> i*20)
let compute = multi20 |> Seq.find checkMod
The first let generates an infinite list of twentyples (I made that one up). The second let finds the first number in said list that passes your test. Your task is to make sure that there actually is a number that will pass the test, but that's of course also true for the imperative code.
If you want to condense the two above lines into one, you can also write
let computeCryptic = Seq.initInfinite ((*) 20) |> Seq.find checkMod
but I find that pulling stunts like that in code can lead to headaches when trying to read it a few weeks later.
In the same spirit as Brian's post, here is another way to get warning FS0020: In a nutshell, I accidentally tupled the function arguments.
Being an F# newbie, I had a difficult time debugging the code below, which for the second line (let gdp...) gave the warning FS0020: This expression should have type 'unit', but has type '(string -> ^a -> unit) * string * float'. It turns out that line was not the problem at all; instead, it was the printfn line that was messed up. Removing the comma separators from the argument list fixed it.
for country in wb.Regions.``Arab World``.Countries do
let gdp = country.Indicators.``GDP per capita (current US$)``.[2010]
let gdpThous = gdp / 1.0e3
printfn "%s, %s (%.2f)" country.Name, country.CapitalCity, gdpThous
I ran into an error similar to this forum post on hubfs, which solved my problem but spawned off some questions about the code in that thread.
let test x = printfn "n"
let finall x = x : 'a -> unit
let i x = finall test x
Can someone explain to me what line 2 is accomplishing?
I see that the type of finall is
finall: ('a -> unit) -> ('a -> unit)
So its just a function that takes in a function and returns that function.
What would be the reason to do lines 2 and 3?
Can you later define a function body to finall?
it appears that you don't have to parenthesize the call on the third line, is that a result of line 2?
Yeah, the code on that thread does not make much sense. 'finall' is basically the identity function (let id x = x) except that it constrains its argument to be a function-returning-unit rather than some arbitrary value. Basically it doesn't do anything useful, you could just as easily write
let test x = printfn "n"
let i x = test x
I expect that this snippet maybe came from someone who started with an error message they didn't understand, and tried to strip it down to a tiny sample repro.
(Regarding function calls, you never need parens to call a let-bound function in F#:
f x
is a call, and function application works in the normal way to support currying, which means
f x y
means
(f x) y
which is what is happening on the 'finall test x' line.)