How can I create an Action<T> in F#? - linq

I am using the Moq framework for unit testing and would like to be able to pass in Action for logging void methods.
let log = new Mock<ILog>()
let quot = <# fun (mock:ILog) -> mock.Info(It.IsAny<string>) #>
let expr = (quot.ToLinqExpression() :?> Expression<Action<ILog>>)
log.Verify(expr)
This code fails with the following error:
System.InvalidCastException : Unable to cast object of type
'System.Linq.Expressions.MethodCallExpressionN' to type
'System.Linq.Expressions.Expression1[System.Action1[log4net.ILog]]'.
I can print the type out using
printfn "%s" (quot.Type.ToString())
which outputs
Microsoft.FSharp.Core.FSharpFunc`2[log4net.ILog,Microsoft.FSharp.Core.Unit]
So, how can I create an Action?

LINQ Expressions are fully supported in F# 3, so you can now pass an Action to Moq as a lambda expression:
let mock = Mock<ILog>()
mock.Verify(fun (log:ILog) -> log.Info(It.IsAny<string>()))

Try:
let quot = <# new Action<_>(fun (mock:ILog) -> mock.Info(It.IsAny<string>)) #>

Related

Using Xamarin Essentials File Picker in Fabulous (F#) UWP app

I am testing out making a UWP app using the Fabulous framework for writing functional cross-platform apps, and I want to use a FilePicker on a button press and use the selected file for some data processing.
Executing
let fileResult = FilePicker.PickAsync() |> Async.AwaitTask opens the file picker and returns a Async<FileResult> after a file is picked (This to say that the button and subsequent function call executes), but the rest of the code following it will execute before the result can be used. If I append |> Async.RunSynchronously it (as expected) blocks the thread and no file can be chosen in the window that appears, although the return value would be the FileResult.
After looking into how this should be done, I realise that the file picker should be opened on the main thread, which leads me to a solution on the following form
let getFileResultAsync =
async {
let tcs = new TaskCompletionSource<FileResult>()
Device.BeginInvokeOnMainThread(fun () ->
async {
let! fileResult = FilePicker.PickAsync() |> Async.AwaitTask
tcs.SetResult(fileResult)
}
|> Async.StartImmediate
)
return! tcs.Task |> Async.AwaitTask
}
which will return Async<FileResult>, but it appears that the Device.BeginInvokeOnMainThread block is never accessed. How would I go about opening the FilePicker, selecting a file and then subsequently process the file in such an app?
I figured out a way to do what I wanted by further looking into the test example and the Fabulous documentation for Updates and messages https://fsprojects.github.io/Fabulous/Fabulous.XamarinForms/update.html.
Basing it off of the standard app that is generated when creating a new Fabulous project, just have a given string in the model for e.g. the file path (I've called it FilePath) for now, and add three additional messages to type Msg as follows
type Msg =
...
| SelectFile
| PresentFile of FileResult
| ErrorFileNotSelected
where the first is sent whenever the button for selecting a file is pressed, the second is sent with the file upon selected and the third is for if a user exits out of the file dialogue without selecting a file.
You need a function to select the file asynchronously
let selectFileAsync =
async {
let! result = FilePicker.PickAsync() |> Async.AwaitTask
return result
}
and a Fabulous.Cmd which calls the above function and sends the message further in the program (probably a better way of explaining that)
let selectFileCmd = async {
let! file = selectFileAsync
match file with
| null -> return Some(ErrorFileNotSelected)
| _ -> return Some(PresentFile file)
}
and finally, add the three following patterns to the update, where selectFileCmd is called under SelectFile
let update msg model =
...
| SelectFile ->
{model with FilePath = "Selecting file"}, (Cmd.ofAsyncMsgOption selectFileCmd)
| PresentFile file ->
{model with FilePath = file.FullPath}, Cmd.none
| ErrorFileNotSelected ->
{model with FilePath = "Error. Must select a file"}, Cmd.none
I am not sure whether this is considered a good approach, but it seems better than utilising let mutable at least.

Play 2.5 Errors with Java 8 - wrong number of type arguments and lambda expression not expected here error

I'm attempting to upgrade from Play 2.4 to Play 2.5. Using the guide from the Replaced F.Promise with Java 8's CompletionStage, I replaced F.Promise, map, and flatMap with the suggested replacements from the previous link (reflected snippet of changes below).
public CompletionStage<Result> parallel() {
final long start = System.currentTimeMillis();
final CompletionStage<WSResponse, Long> getLatency = resp -> System.currentTimeMillis() - start;
CompletionStage<Long> googleLatency = WS.url("http://google.com").get().thenApplyAsync(getLatency);
CompletionStage<Long> yahooLatency = WS.url("http://yahoo.com").get().thenApplyAsync(getLatency);
return googleLatency.thenComposeAsync(googleResponseTime ->
yahooLatency.thenApplyAsync(yahooResponseTime ->
ok(format("Google response time: %d; Yahoo response time: %d",
googleResponseTime, yahooResponseTime)))
);
}
After running ./activator clean dist, I'm getting the error below:
[error] /Play-2-JS-2.5/app/controllers/Java8Controller.java:74: wrong number of type arguments; required 1
[error] CompletionStage
[error] /Play-2-JS-2.5/app/controllers/Java8Controller.java:74: lambda expression not expected here
[error] resp -> System.currentTimeMillis() - start
For some reason, it believes it should have only one instead of two in the CompletionStage<WSResponse, Long> getLatency section and also for some reason it's not liking the lambda expression even though the syntax before the new api replacements worked successfully in Play 2.4.
I tried switching back to the old calls to what is displayed in https://github.com/btgrant-76/Play-2-Java-Scala-Java-8-Async-Comparison/blob/6a85cf31cfb804ef20bacf8e14d30ce46cc9307c/app/controllers/Java8Controller.java#L71-L83 however it doesn't lend any better results. Been googling and searching for sometime but not sure how to approach this. Any suggestions with possible examples would be greatly appreciated.
Replace
final CompletionStage<WSResponse, Long> getLatency = resp ->
System.currentTimeMillis() - start;
with
final Function<WSResponse, Long> getLatency = resp -> System.currentTimeMillis() - start;
since thenApplyAsync metod in CompletionStage interface accepts a java.util.Function
Hope this helps.
Good luck

FsPlot for osx sierra

I have got an error message with the following code: (example code from sudipta mukherjee)
#load "./packages/FsPlot.0.6.6/FsPlotBootstrap.fsx"
open FsPlot.Highcharts.Charting
// Logistic Regression
let z = [for i in -10. .. 10. -> (i,1./(1.+exp -i))]
z
|> Chart.Spline
|> Chart.WithTitle "Sigmoid Function"
|> Chart.WithName "g(z)"
When I execute the code, I have got an error message in FSI:
Loading /eUSB/sync/fsharp/packages/FsPlot.0.6.6/FsPlotBootstrap.fsx]
namespace FSI_0008
System.ComponentModel.Win32Exception: ApplicationName='/eUSB/sync/fsharp/packages/FsPlot.0.6.6/./tools/chromedriver.exe',
CommandLine='--port=53810', CurrentDirectory='', Native error= Access denied
at System.Diagnostics.Process.Start_noshell (System.Diagnostics.ProcessStartInfo startInfo, System.Diagnostics.Process p
rocess) <0x11eab6f10 + 0x006f3> in <filename unknown>:0
Stopped due to error
It seems the error is win32 related and FsPlot doesn't support OSX.
Please feel free to advise. What I should do to fix the error?
Migrated source code to XPlot (part of FsLab package), it is running smoothly.
#load "./packages/FsLab.1.0.2/FsLab.fsx"
open XPlot.GoogleCharts
// Logistic Regression
let z = [for i in -10. .. 10. -> (i,1./(1.+exp -i))]
let options =
Options
( title = "Sigmoid Function", curveType = "function",
legend = Legend(position = "bottom") )
[z]
|> Chart.Line
|> Chart.WithOptions options
|> Chart.WithLabels ["g(z)"]

Using apply functions in SparkR

I am currently trying to implement some functions using sparkR version 1.5.1. I have seen older (version 1.3) examples, where people used the apply function on DataFrames, but it looks like this is no longer directly available. Example:
x = c(1,2)
xDF_R = data.frame(x)
colnames(xDF_R) = c("number")
xDF_S = createDataFrame(sqlContext,xDF_R)
Now, I can use the function sapply on the data.frame object
xDF_R$result = sapply(xDF_R$number, ppois, q=10)
When I use a similar logic on the DataFrame
xDF_S$result = sapply(xDF_S$number, ppois, q=10)
I get the error message "Error in as.list.default(X) :
no method for coercing this S4 class to a vector"
Can I somehow do this?
This is possible with user defined functions in Spark 2.0.
wrapper = function(df){
+ out = df
+ out$result = sapply(df$number, ppois, q=10)
+ return(out)
+ }
> xDF_S2 = dapplyCollect(xDF_S, wrapper)
> identical(xDF_S2, xDF_R)
[1] TRUE
Note you need a wrapper function like this because you can't pass the extra arguments in directly, but that may change in the future.
The native R functions do not support Spark DataFrames. We can use user defined functions in SparkR to execute native R modules. These are executed on the executors and thus the libraries must be available on all the executors.
For example, suppose we have a custom function holt_forecast which takes in a data.table as an argument.
Sample R code
sales_R_df %>%
group_by(product_id) %>%
do(holt_forecast(data.table(.))) %>%
data.table(.) -> dt_holt
For using UDFs, we need to specify the schema of the output data.frame returned by the execution of the native R method. This schema is used by Spark to generate back the Spark DataFrame.
Equivalent SparkR code
Define the schema
structField("product_id", "integer"),
structField("audit_date", "date"),
structField("holt_unit_forecast", "double"),
structField("holt_unit_forecast_std", "double")
)
Execute the method
library(data.table)
library(lubridate)
library(dplyr)
library(forecast)
sales <- data.table(x)
y <- data.frame(key,holt_forecast(sales))
}, dt_holt_schema)
Reference: https://shbhmrzd.medium.com/stl-and-holt-from-r-to-sparkr-1815bacfe1cc

Spying on a Javascript constructor using Jasmine

I'm writing specs for some Javascript classes (backbone.js views, written in Coffeescript) and I'd like to ensure that one view constructs another.
I'm attempting to do this by spying on the constructor, like so:
describe 'Avia.AviaView', ->
beforeEach ->
#aviaView = new Avia.AviaView()
#matricesView = new Backbone.View()
spyOn(Avia.MatricesView, 'constructor').andReturn #matricesView
describe 'initialize', ->
beforeEach ->
#aviaView.initialize()
it 'creates a new MatricesView ', ->
expect(Avia.MatricesView.constructor).toHaveBeenCalledOnce()
The initialize() call on AviaView definitely causes the MatricesView constructor to be called, courtesy this line:
new Avia.MatricesView($("#tabs-3")).initialize()
It definitely works; if I run the app manually I can see the constructor being called during initialize(). However my Jasmine spec fails:
Running Jasmine specs...
F
Avia.AviaView initialize creates a new MatricesView . (/Users/dev/avia/spec/javascripts/views/avia_view_spec.js.coffee:13)
Expected constructor to be called exactly once, but was called '0' times (line ~14)
expect(Avia.MatricesView.constructor).toHaveBeenCalledOnce();
FAIL: 1 test, 1 failure, 0.008 secs.
I've spoken to several of my colleagues, and they agree that this should work ... can anyone suggest a good way of spying on constructors?
How about:
describe 'Avia.AviaView', ->
beforeEach ->
#aviaView = new Avia.AviaView()
#matricesView = new Backbone.View()
spyOn(Avia, 'MatricesView').andReturn #matricesView
describe 'initialize', ->
beforeEach ->
#aviaView.initialize()
it 'creates a new MatricesView ', ->
expect(Avia.MatricesView).toHaveBeenCalledOnce()

Resources