I could not figure out how to create a router actor in f#. And the f# Api page does not offer much help either. Any sample code is very much appreciated.
One way is to define routers via HOCON config - this looks the same for both C# and F# versions.
In case of Akka.FSharp plugin, you can define router programaticaly: let actorRef = spawnOpt system actorName actorBehavior [ Router(routerConfig) ]
In case of Akkling plugin, you can define it like: let actorRef = spawn system actorName { props(actorBehavior) with Router = routerConfig }
Related
I've seen a few posts about implementing log4net using C# and F# - but I am wanting to implement it as a singleton in a separate class ( so I can call from anywhere )
I am loosely following this post. I just think my translation from C# to F# is a bit behind.
I set up the log4net.config and run the following code at the start of my console app
namespace MyNamespace
open System.IO
open log4net.Config
module LoggerConfigure =
let configureLogging() =
FileInfo("log4net.config")
|> XmlConfigurator.Configure
|> ignore
The following ( from the link above ) is C# and I want it to be an F# class that can be called as a singleton.
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
My primary quwation is - I'm a bit stuck converting that to an F# class. How do I do that?. Any ideas you have around the whole concept is appreciated as well.
There may be cases where a more sophisticated handling of singletons is needed, but I believe that standard global let declaration in an F# module would work well enough.
You just need to make sure that the configuration code is run before the log value is accessed, which you can do by making that call as part of the let binding that defines log:
module LoggerConfigure =
let configureLogging() =
FileInfo("log4net.config")
|> XmlConfigurator.Configure
|> ignore
log4net.LogManager.GetLogger
(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType)
let log = configureLogging()
Or if you prefer to put everything in a single expression:
module LoggerConfigure =
let log =
FileInfo("log4net.config") |> XmlConfigurator.Configure |> ignore
log4net.LogManager.GetLogger
(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType)
I am a newbie to Elmish.WPF and F#. In studying the tutorial on NewWindow/NewWindow.Views, the authors have assigned the following code from C# :
using System;
using Elmish.WPF.Samples.NewWindow;
using static Elmish.WPF.Samples.NewWindow.Program;
namespace NewWindow.Views {
public static class Program {
[STAThread]
public static void Main() =>
main(new MainWindow(), () => new Window1(), () => new Window2());
}
}
That is calling the main method in the F# NewWindow.Views project:
let main mainWindow (createWindow1: Func<#Window>) (createWindow2: Func<#Window>) =
let createWindow1 () = createWindow1.Invoke()
let createWindow2 () =
let window = createWindow2.Invoke()
window.Owner <- mainWindow
window
let bindings = App.mainBindings createWindow1 createWindow2
Program.mkSimpleWpf App.init App.update bindings
|> Program.withConsoleTrace
|> Program.runWindowWithConfig
{ ElmConfig.Default with LogConsole = true; Measure = true }
mainWindow
How can the F# module main routine be changed so as to use it directly as the EntryPoint and avoid it being a function? That is, I would like the F# module to have direct control over the windows via Elmish. Something along the lines as below but with the invocation of the subordinate windows self-contained:
/// This is the application's entry point. It hands things off to Elmish.WPF
[<EntryPoint; STAThread>]
let main _ =
Program.mkSimpleWpf init update bindings
|> Program.runWindow (MainWindow())
In short, I would like the C# Views to have no knowledge of the F# project.
Can this be done with Elmish.wpf?
Any help (especially sample code :) ) would be most helpful.
I am one of the maintainers of Elmish.WPF. Until very recently, all the samples used their F# project as the entry point. If you clone the repo and check out this commit, then you can inspect those samples and see how to achieve your goal.
Going forward, I created this issue to consider including at least one sample with an F# project as its entry point.
In the future, feel free to ask any of your Elmish.WPF questions by opening an issue in our GitHub.
I am a newbie to F#. I have recently be introduced to Elmish.wpf and the MVU design. The application I am working with is in C# WPF with many WPF usercontrols, customcontrols, and windows. It appears that Elmish.wpf flattens the concept of viewmodels into a single datacontext. (??). Can Elmish.wpf be used with multiple windows, usercontrols, and customcontrols? ("Multiple" here means about 20 windows, usercontrols, and customcontrols.)
If so, is there an example of this?
In looking at the Elmish.wpf webside, it seems that all windows need to be created upon initialization--
let main mainWindow (createWindow1: Func<#Window>) (createWindow2: Func<#Window>) =
let createWindow1 () = createWindow1.Invoke()
let createWindow2 () =
let window = createWindow2.Invoke()
window.Owner <- mainWindow
window
let bindings = App.mainBindings createWindow1 createWindow2
Program.mkSimpleWpf App.init App.update bindings
|> Program.withConsoleTrace
|> Program.runWindowWithConfig
{ ElmConfig.Default with LogConsole = true; Measure = true }
mainWindow
Is there a better way to do this? Am I barking up the wrong tree?
Thanks in advance.
Yes, Elmish.WPF absolutely supports multiple windows and user-defined controls.
Many of the samples in the Elmish.WPF repo demonstrate this one way or another. For example, the NewWindow sample demonstrates how to open new windows, and the SubModel (along with many others) sample demonstrates how to use custom UserControls. The SubModelSeq sample is currently the most complex one, demonstrating arbitrarily deep trees of recursive UserControls.
All of this is also described in the official Elmish.WPF tutorial.
(For future reference, this is the current commit at the time of writing; the samples may have changed since then.)
I prefer to model business requirements as function types within a code base:
type Subscribe = SubscribeRequest -> Result<SubscribedCourier,ErrorDescription>
Then I implemented a function that complies with a function type:
let subscribe : Publish.Subscribe =
fun request ->
let subscribed = request |> toSubscribedCourier
...
Ok subscribed
Issue:
The above function is fine when implementing a unit test. However, when the above function needs to rely on an external system to complete its task, then I believe that the function requires an async modifier for that function signature.
As a result, I'm now obligated to update my function type to the following:
type Subscribe = SubscribeRequest -> Async<Result<SubscribedCourier,ErrorDescription>>
Thus, my actual function that needs to await an external system's response looks like this:
let subscribe : Publish.Subscribe =
fun request ->
async {
let subscribed = request |> toSubscribedCourier
let json = JsonConvert.SerializeObject subscribed
let buffer = Encoding.ASCII.GetBytes(json)
let message = Message(buffer)
let topicClient = new TopicClient("MyConnectionString","Subscription.subscribed")
do! topicClient.SendAsync(message) |> Async.AwaitTask
return Ok subscribed
}
Although, the above function type is correct for returning an Async result type, it's now a leaky abstraction for how the function executes. I really want to only specify business requirements through function types and have my functions map to those function types as if they were contacts.
Question:
In conclusion, how do I expose a function type as a business requirement without exposing its asynchronous dependency?
I don't know why you want to define a type alias for a function, but I do agree that if you want to implement a functional architecture, business logic shouldn't be asynchronous. In F# I think that it makes sense to view asynchronicity as implying impurity. You rarely need to return asynchronous workflows unless you're performing I/O.
I think that one should keep the domain model pure, so, as you write, returning an asynchronous workflow is a leaky abstraction.
You can often address the issue by refactoring to an impure-pure-impure sandwich. This also seems to be the case here. As far as I can tell, the work to actually put a message on a queue looks to be entirely generic. I suppose you could extract that into a helper function, like this:
let send x =
let json = JsonConvert.SerializeObject x
let buffer = Encoding.ASCII.GetBytes json
let message = Message buffer
let topicClient = new TopicClient ("MyConnectionString", "Subscription.subscribed")
do! topicClient.SendAsync message |> Async.AwaitTask
return Ok x
(I haven't tried to compile this, so there may be minor issues.)
You can now create the sandwich as a straightforward composition:
let sandwich = toSubscribedCourier >> send
(Again, this may not compile, but hopefully gets the point across.)
It's possible that there's little to no logic in toSubscribedCourier, but that's just the reality of things, then. As I've written in a recent article on the same general topic:
Once you remove all the accidental complexity, you uncover the essential complexity.
Perhaps there isn't much domain logic, but that fact is only laid bare once you start separating the pure functions from the impure actions.
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() :> _