how do i create a computational expression that takes parameters? - f#

I want to create a couple of computational expressions that would be used to access the database and return a list of items like so (I also have questions in the code comments):
let foo x y z = proc "foo" {
let! cmd = proc.CreateCommand() // can I do this?
do! In "x" DbType.Int32 // would i gain anything by replacing DbType with a union
// type since the names would match actual data types?
do! In "y" DbType.String 15;
cmd?x <- x
cmd?y <- y
use! r = cmd.ExecuteReader() // would this be bad form for creating a workflow builder?
return! r {
let item = MyItem()
do! item.a <- r.GetInt32("a")
do! item.a <- r.GetString("b")
do! item.c <- r.GetDateTime("c")
yield! item
}
}
How can I create a workflow builder such that an instance of it takes a parameter?
let proc name = ProcedureBuilder(connStr, factory) // how do I do this?

Yes, you can do this. You can use computation expression syntax after any expression with a type statically known to expose the right methods. So the following code works (but doesn't do anything particularly interesting):
let f x = async
let v = f "test" { return 1 }
Here, f has type 'a -> AsyncBuilder, so f "test" has type AsyncBuilder and can be followed with computation expression syntax. Your example of let proc name = ProcedureBuilder(connStr, factory) is perfectly fine, assuming that ProcedureBuilder is defined appropriately, though you presumably want name to appear somewhere in the constructor arguments.

The answer from Keith (kvb) is correct - you can use parameterized computation builders. The syntax of computation expressions is:
<expr> { <cexpr> }
So, the builder can be created by any expression. Usually, it is some value (e.g. async) but it can be a function call or even a constructor call. When using this, you would typically define a parameterized builder and then pass the argument to a constructor using a function (as #kvb suggests).
I actually wrote an example of this, not a long time ago, so I can share an example where - I think - this is quite useful. You can find it on F# snippets: http://fssnip.net/4z
The example creates a "special" asynchronous computation builder for ASP.NET MVC that behaves just like standard async. The only difference is that it adds Run member that uses AsyncManager (provided by ASP.NET) to execute the workflow.
Here are some relevant parts from the snippet:
/// A computation builder that is almost the same as stnadard F# 'async'.
/// The differnece is that it takes an ASP.NET MVC 'AsyncManager' as an
/// argumnet and implements 'Run' opration, so that the workflow is
/// automatically executed after it is created (using the AsyncManager)
type AsyncActionBuilder(asyncMgr:Async.AsyncManager) =
// (Omitted: Lots of boilerplate code)
/// Run the workflow automatically using ASP.NET AsyncManager
member x.Run(workflow) =
// Use 'asyncMgr' to execute the 'workflow'
The snippet wraps the construction in a base class, but you could define a function:
let asyncAction mgr = new AsyncActionBuilder(mgr)
And then use it to define asynchronous action in ASP.NET MVC:
member x.LengthAsync(url:string) = asyncAction x.AsyncManager {
let wc = new WebClient()
let! html = wc.AsyncDownloadString(url)
return html.Length }

Related

Pass value to second parameter in a pipeline

what's the correct way to pass a value to the second paramater of a function in a pipeline?
e.g.
async {
let! response =
someData
|> JsonConvert.SerializeObject
|> fun x -> new StringContent(x)
|> httpClient.PostAsync "/DoSomething"
|> Async.AwaitTask
}
in the above code PostAsync takes 2 parameters, the url to post to and the content you want to post. Have tried the back pipe too, and parenthesis, but cant quite figure out how to do it
any ideas?
PostAsync has non-curried parameters, which cannot be passed in one by one, they have to be passed all at once. This is why you should always have your parameters curried.
But alas, you can't control the definition of PostAsync, because it's a .NET library method, so you have to wrap it one way or another. There are a few options:
Option 1: use a lambda expression:
|> fun body -> httpClient.PostAsync( "/DoSomething", body )
Option 2: declare yourself a function with curried parameters
let postAsync client url body =
client.PostAsync(url, body)
...
|> postAsync httpClient "/DoSomething"
This is usually my preferred option: I always wrap .NET APIs in F# form before using them. This is better, because the same wrapper can transform more than just parameters, but also other things, such as error handling or, in your case, async models:
let postAsync client url body =
client.PostAsync(url, body)
|> Async.AwaitTask
Option 3: go super general and make yourself a function for transforming any functions from non-curried to curried. In other functional languages such function is usually called uncurry:
let uncurry f a b = f (a, b)
...
|> uncurry httpClient.PostAsync "/DoSomething"
One problem with this is that it only works for two parameters. If you have a non-curried function with three parameters, you'd have to create a separate uncurry3 function for it, and so on.
In F#, you often need to work with .NET APIs that are not designed to work well as functional pipelines. In those cases, you can do various tricks to fit it into an (often very ugly) pipeline, or you can use the fact that F# is multi-paradigm and write the code in a more object-oriented style.
In your example, I would just use more C#-like style, because the code is not very pipeline-friendly:
async {
let serialized = JsonConvert.SerializeObject(someData)
let postData = new StringContent(serialized)
let! response = httpClient.PostAsync("/DoSomething", postData) |> Async.AwaitTask
}
I think there is also a good theoretical reason why this should not be a pipe - typically, pipelines work well if you have some "main entity" that you are transforming through a series of operations. This can often be some generic type such as list<'a> or non-generic type like Chart.
In your example, you start with object, turn it into JSON, then turn that into StringContent, then Task<'T> etc. - in other words, it's not transforming an entity - it's just doing a lot of unrelated things. In those situations, I prefer to use more explicit coding style rather than pipe.

What's wrong with the following FsCheck test

It's probably something very simple, but I'm new to FsCheck and not sure why the below raises the error it does ("Geneflect: type not handled System.Numerics.BigInteger")?
open System.Numerics
type NumericGenerator =
/// Generating BigIntegers (though only in the regular integer range for now)
static member BigInt() =
{ new Arbitrary<System.Numerics.BigInteger>() with
override x.Generator =
Arb.generate<int>
|> Gen.map (fun i -> new BigInteger(i)) }
[<Property>]
let ``Simple test`` (b: BigInteger) =
Arb.register<NumericGenerator> |> ignore
b + 1I = 1I + b
This is using FsCheck with xUnit integration.
FsCheck is trying to generate a BigInteger before calling your test, because the Arb.register call is in your test method itself. It then tries to do that via reflection, which fails.
You can tell FsCheck about your custom arbitrary instance by adding it as a argument to your property.
[<Property(Arbitrary=[|typeof<NumericGenerator>|])>]
Also, you can add the ArbitraryAttribute to the test's enclosing module to register that arbitrary instance for all the properties in the module. See https://github.com/fsharp/FsCheck/blob/master/tests/FsCheck.Test/Runner.fs for some examples.
One final tip - if you are generating a type that's easily converted to/from another already generated type, you can easily create a generate and a shrinker using the Arb.convert method. Something like:
Arb.Default.Int32() |> Arb.convert ...
shoud work.

How to pass a static parameter to a typeprovider in f# inside a function

I'm using the FSharp.Data typeproviders.
I would like to make a function that has a parameter that sets the typeprovider's sample string or file location.
let SyncIt url sample converter storer =
async {
url
|> MakeRequestAsync
|> Async.RunSynchronously
|> JsonProvider< sample >.Parse
|> Seq.iter (converter >> storer)
}
If a call the JsonProvider in the module with
[<Literal>]
let sample = """{"name":"Peter","age":9}"""
type provider = JsonProvider<sample>
works fine. Why can't I pass it as a parameter? I know it has something to do with the reference being clear at compile time, but cannot figure out how to get around it other than declaring each providers explicitly.
A function cannot take a value of static parameter as an argument, because the value has to be determined at compile time. This means that if you write:
let [<Literal>] sample = """{"name":"Peter","age":9}"""
let parseHtml html = JsonProvider<sample>.Parse(html)
... everything is fine, because the compiler knows that sample is a constant (and the compiler knows its value) and so it can instantiate the type provider (during compilation) to generate types. If you write something like:
let parseHtml sample html = JsonProvider<sample>.Parse(html)
... then the compiler cannot know what the value of sample may be at runtime and so it cannot generate the required types at compile time. Type providers do not "exist" at runtime, so the types cannot be generated on the fly (This would not be really useful, because the point of type providers is to give you some compile-time safety guarantees).
Your example. In your case, it might make sense to take the specific JsonProvider<sample>.Parse function as an argument instead:
let SyncIt url parse storer =
async {
url
|> MakeRequestAsync
|> Async.RunSynchronously
|> parse
|> Seq.iter (converter >> storer)
}
This way, the caller can specify the static parameter to a type provider and then call your function to do the synchronization:
let [<Literal>] sample = """{"name":"Peter","age":9}"""
SyncIt url (JsonProvider<sample>.Parse) storer
Although, it is not entirely clear to me why you need a type provider here. The point of providers is to give you nice types that you can use to access a concrete source of data. If your converter and storer work on any JSON data file, then you might be able to get the thing done using just JSON parser (also in F# Data).
Asynchronous block. Also, note that your code is not really running asynchronously - to make it asynchronous, you need to download the URL using let! operation:
let SyncIt url parser storer =
async {
let wc = new WebClient()
let! html = wc.AsyncDownloadString(url)
parser html
|> Seq.iter (converter >> storer)
}

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() :> _

Formatting fluent/method chaining code from C# in F#

Some apis like Ninject use fluent style apis, example:
Bind<ISomething>()
.To<Something>()
.WithConstructorArgument("arg1", "somevalue")
.OnActivation(x => x.DoSomething())
When I try format the code like this in F# the compiler complains at the whitespace between method calls.
Is it possible to put the method calls on seperate lines? I was thinking something like the pipelining operator |> but not exactly sure how in this case.
How should this be formatted in F#?
Are you sure this doesn't work?
Bind<ISomething>()
.To<Something>()
.WithConstructorArgument("arg1", "somevalue")
.OnActivation(fun x -> x.DoSomething())
(note one space before the .s)
Yeah, it's fine:
type ISomething = interface end
type Something = class end
type Foo() =
member this.To<'a>() = this //'
member this.WithConstructorArgument(s1,s2) = this
member this.OnActivation(x:Foo->unit) = this
member this.DoSomething() = ()
let Bind<'a>() = new Foo() //'
let r =
Bind<ISomething>()
.To<Something>()
.WithConstructorArgument("arg1", "somevalue")
.OnActivation(fun x -> x.DoSomething())
So long as you have some leading whitespace when you try to continue a single expression onto multiple lines, you're ok.
(Note that pipelining in general won't work unless you have APIs designed for it with curried method parameters.)

Resources