How to use FileSystemWatcher in F# - f#

I want to watch a directory for file changes (create, edit, rename, delete) and do something, such as calling a function, when a change is detected. From what I can tell, FileSystemWatcher should do this. However, there is no sample code for F# on the documentation page, and elsewhere on the web seems scarce as well.
From what I've found, the following is at least part of the answer:
let fileSystemWatcher = new FileSystemWatcher()
fileSystemWatcher.Path <- #"C:\temp" // I'm actually using a variable here
fileSystemWatcher.NotifyFilter <- NotifyFilters.LastWrite
fileSystemWatcher.EnableRaisingEvents <- true
fileSystemWatcher.IncludeSubdirectories <- true
fileSystemWatcher.Changed.Add(fun _ -> printfn "changed")
fileSystemWatcher.Created.Add(fun _ -> printfn "created")
fileSystemWatcher.Deleted.Add(fun _ -> printfn "deleted")
fileSystemWatcher.Renamed.Add(fun _ -> printfn "renamed")
That doesn't actually do anything, however. Some posts seem to have an Async loop to react to events, but if I use the code snippets from there F# tells me that Async.AwaitObservable is undefined.
I'd appreciate it if someone could provide a complete example of FileSystemWatcher's correct usage.

Works fine for me in FSI.
Drop the NotifyFilter bit - you're overwriting the default settings (which do include LastWrite anyway), and some of the events you care about are not being raised. NotifyFilter is an antiquated enum-flag-style field, so you can add a new value there like this:
watcher.NotifyFilter <- watcher.NotifyFilter ||| NotifyFilters.LastWrite
You don't need an async loop per se - in the example you linked to it just replaces the standard event handlers that you are already using. But if you want to use Async.AwaitObservable, look up FSharpx on nuget.

Related

How to unsubscribe an event from inside the event handler?

My code subscribes to an event and it needs to unsubscribe (Dispose) once the event has been handled. However this looks like a chicken-egg problem. Using rec doesn't work and I cannot find how to do it.
It there any well-konwn pattern to bypass this limitation?
let process = new Process()
let exitSubscription = process.Exited.Subscribe (
fun evntArg ->
exitSubscription.Dispose() <---------- Compiler complains here
// do more something here.
)
(you're saying in your question that rec doesn't work, but do not clarify why or how; so I'm going to ignore that part for this answer)
One way to do this is to declare the value "recursive" with the rec keyword. This will allow the value initialization code to reference the value itself - just like with a recursive function.
let rec exitSubscription : IDisposable = process.Exited.Subscribe (
fun evntArg ->
exitSubscription.Dispose()
// do more something here.
)
This will work, but will also produce a warning saying "this is a recursive value, and I can't tell if you're actually accessing it while it's being constructed, so you have to make sure that you don't, and if you do anyway, it'll be a runtime error".
Note that you also have to add a type signature to the variable, otherwise the compiler can't quite grok it and complains that it might not have a Dispose method.
Another way is to make the variable mutable and then mutate it:
let mutable exitSubscription : IDisposable = null
exitSubscription <- process.Exited.Subscribe (
fun evntArg ->
exitSubscription.Dispose()
// do more something here.
)
Here you have to use a type signature too (for the same reason), and you have to initialize it with null, because there is no such thing as an uninitialized variable.
Also, this is a tiny bit less safe, because the variable is mutable, and that's always a source of bugs. As long as you pinky-promise not to mutate it (beyond this initialization), you're ok.
But a "proper" way is to use an observable combinator to limit the observable to only one element. That way you don't have to unsubscribe explicitly, which is always more reliable:
#r "nuget: System.Reactive"
open System.Reactive.Linq
process.Exited.Take(1).Subscribe (
fun evntArg ->
// do more something here.
)

Difference between an F# function name and a function value pointed at that name

I'm using the following code snippet in a WPF / FsXaml application:
let groupSelected(e: SelectionChangedEventArgs) =
e.AddedItems
|> Seq.cast<string>
|> Seq.head
|> SelectedGroupChanged
let GroupSelected = groupSelected
When I mouse-over groupSelected, Visual Studio shows the following:
val groupSelected: e:SelectionChangedEventArgs -> ClientGroupEvent
It is slightly different for GroupSelected:
val GroupSelected: (SelectionChangedEventArgs -> ClientGroupEvent)
I have noticed this difference before in other contexts and never thought much of it. If I want to invoke either one, the syntax in my code is the same... groupSelected(e) and GroupSelected(e) both compile fine.
However, when I try to use these two from XAML only this works:
{x:Static local:EventConverters.GroupSelected}
This does not work:
{x:Static local:EventConverters.groupSelected}
What is the difference between those two such that XAML Static extension only works with the second? I would have (mistakenly?) thought they were the same thing.
This is one of the areas where simple functional ideas are made a bit more complicated by living in the .NET framework world. F# indeed compiles your groupSelected and GroupSelected in two different ways.
The IntelliSense does tell you this. Most of the time, this is not something you need to worry about, and it is quite sensible to see the following two as the same thing (and, as far as F# itself is concerned, they are):
val groupSelected: e:SelectionChangedEventArgs -> ClientGroupEvent
val GroupSelected: (SelectionChangedEventArgs -> ClientGroupEvent)
The key difference is that the two will be compiled diferently. The first one as a method and the second one as a property that returns a function value. Using C# notation:
// groupSelected is compiled as a method:
ClientGroupEvent groupSelected(SelectionChangedEventArgs e);
// GroupSelected is compiled as a property:
FSharpFunc<SelectionChangedEventArgs, ClientGroupEvent> GroupSelected { get; }

Result vs raise in F# async?

It seems like there are two ways to return errors in an async workflow: raise and Result.
let willFailRaise = async {
return raise <| new Exception("oh no!")
}
let willFailResult = async {
return Result.Error "oh no!"
}
For the caller, the handling is a bit different:
async {
try
let! x = willFailRaise
// ...
with error ->
System.Console.WriteLine(error)
}
async {
let! maybeX = willFailResult
match maybeX with
| Result.Ok x ->
// ...
| Result.Error error ->
System.Console.WriteLine(error)
}
My questions are:
What are the advantages / disadvantages of each approach?
Which approach is more idiomatic F#?
It depends on what kind of error we are talking about. Basically there are three kinds:
Domain errors (e.g. user provided invalid data, user with this email is already registered, etc.)
Infrastructure errors (e.g you can't connect to another microservice or DB)
Panics (e.g. NullReferenceExceptionor StackOverflowException etc.), which are caused by programmers' mistakes.
While both approaches can get the job done, usually your concern should be to make your code as self-documented and easy-to-read as possible. Which means the following:
Domain errors: definitely go for Result. Those "errors" are expected, they are part of your workflow. Using Result reflects your business rules in function's signature, which is very useful.
Infrastructure failures: it depends. If you have microservices, then probably those failures are expected and maybe it would be more convenient to use Result. If not -- go for exceptions.
Panics: definitely Exception. First of all, you can't cover everything with Result, you gonna need global exception filter either way. Second thing -- if you try to cover all possible panics - code becomes a nasty disaster extremely fast, that will kill the whole point of using Result for domain errors.
So really this has nothing to do with Async or C# interop, it's about code readability and maintainability.
As for C# iterop -- don't worry, Result has all the methods to help, like IsError and so on. But you can always add an extension method:
[<AutoOpen>]
module Utils =
type Result<'Ok, 'Error> with
member this.Value =
match this with
| Ok v -> v
| Error e -> Exception(e.ToString()) |> raise
This is one of the many aspects of F# programming that suffers from the mind-split at the core of the language and its community.
On one hand you have "F# the .NET Framework language" where exceptions are the mechanism for handling errors, on the other - "F# the functional programming language" that borrows its idioms from the Haskell side of the world. This is where Result (also known as Either) comes from.
The answer to the question "which one is idiomatic" will change depending who you ask and what they have seen, but my experience has taught me that when in doubt, you're better off using exceptions. Result type has its uses in moderation, but result-heavy programming style easily gets out of hand, and once that happens it's not a pretty sight.
Raise
Advantages
Better .NET interop as throwing exceptions is fairly common in .NET
Can create custom Exceptions
Easier to get the stack trace as it's right there
You probably have to deal with exceptions from library code anyways in most standard async operations such as reading from a webpage
Works with older versions of F#
Disadvantages:
If you aren't aware of it potentially throwing an exception, you might not know to catch the exception. This could result in runtime explosions
Result
Advantages
Any caller of the async function will have to deal with the error, so runtime explosions should be avoided
Can use railway oriented programming style, which can make your code quite clean
Disadvantages
Only available in F# 4.1 or later
Difficult for non-F# languages to use it
The API for Result is not comprehensive.
There are only the functions bind, map, and mapError
Some functions that would be nice to have:
bimap : ('TSuccess -> 'a) -> ('TError -> 'e) -> Result<'TSuccess,'TError> -> Result<'a, 'e>
fold : ('TSuccess -> 'T) -> ('TError -> 'T) -> Result<'TSuccess, 'TError> -> 'T
isOk

Usage of AddXmlDocComputed in an F# type provider

I have a type provider which provides a static property but the documentation is subject to change at recurring intervals throughout. I have the following property setup.
let prop = ProvidedProperty("Test", typeof<string>,
IsStatic = true,
GetterCode = fun args -> <## "Test" ##>)
I then tried to add some documentation to it with AddXmlDocComputed as follows
let GetDocumentation () = "Test documentation"
do prop.AddXmlDocComputed(GetDocumentation)
However, I get no text displayed in the Intellisense comments. I then raised an exception in the GetDocumentation function which is reflected in the intellisense through the addition of the [<Note>] and the message saying that it originated from the call to GetDocumentation. I also tried using AddXmlDoc and AddXmlDocDelayed, both of which added the documentation as expected.
So this leads to my question of does anyone have any experience using AddXmlDocComputed and why does my current implementation add no documentation to the property?
Edit:
I've now tried debugging a VS2013 instance and can see that the documentation is being called and the expected string is being passed through the type provider for that property, however, there is still no documentation appearing in the Intellisense window.
I believe this to be a bug in ProvidedTypes.fs. The explanation is that the computed XML doc attribute is never actually returned when GetCustomAttributesData() in type CustomAttributesImpl(). Instead of returning the attribute as part of the array of attributes, it is added to an internal list of attributes (by accident I assume).
To fix the issue locally, replace the implementation with this code:
member __.GetCustomAttributesData() =
[| yield! customAttributesOnce.Force()
match xmlDocAlwaysRecomputed with None -> () | Some f -> yield mkXmlDocCustomAttributeData (f()) |]
:> IList<_>
I have issued a pull request on GitHub with the fix.
Update:
The fix has been merged into the master branch of FSharp.TypeProviders.StarterPack.

Is there any way to use JavaScript attribute by default?

I just want somehow to say "I want all methods in this project use [JavaScript]"
Manually annotation every method is annoying
F# 3 lets you mark a module with the ReflectedDefinition attribute (aka [JavaScript] in WebSharper) which marks all the methods underneath.
See More About F# 3.0 Language Features:
(Speaking of uncommon attributes, in F# 3.0, the
[< ReflectedDefinition >] attribute can now be placed on modules and
type definitions, as a shorthand way to apply it to each individual
member of the module/type.)
I think Phil's answer is the way to go - when you can mark an entire module or type, it does not add too much noise and it also allows you to distinguish between server-side and client-side code in WebSharper.
Just for the record, the F# compiler is open-source and so someone (who finds this issue important) could easily create branch that would add an additional command line attribute to override the setting. I think this is just a matter of adding the parameter and then setting the default value of the reflect flag in check.fs (here is the source on GitHub).
At the moment, the main F# repository does not accept contributions that add new features (see the discussion here), but it is certainly a good way to send a feature request to the F# team :-)
If you annotate all your code with the JavaScript attribute, the WebSharper compiler will try to translate everything to JavaScript. A rule of thumb in WebSharper development is to separate server-side and client-side code, so you can simply annotate the module/class containing client-side code instead of every function/member if you're targeting .NET 4.5.
namespace Website
open IntelliFactory.WebSharper
module HelloWorld =
module private Server =
[<Rpc>]
let main() = async { return "World" }
[<JavaScript>] // or [<ReflectedDefinition>]
module Client =
open IntelliFactory.WebSharper.Html
let sayHello() =
async {
let! world = Server.main()
JavaScript.Alert <| "Hello " + world
}
let btn =
Button [Text "Click Me"]
|>! OnClick (fun _ _ ->
async {
do! sayHello()
} |> Async.Start)
let main() = Div [btn]
type Control() =
inherit Web.Control()
[<JavaScript>]
override __.Body = Client.main() :> _

Resources