Reputation: 3528
So i have this as a script:
#r @"..\packages\FSharp.Data.2.4.2\lib\net45\FSharp.Data.dll"
#r "System.Xml.Linq.dll"
open FSharp.Data
// provide some URL, file path, or raw JSON sample
// that can be used at compile time to generate types
type Json = JsonProvider<"example.json">
// at runtime, load up new sample matching that schema
let response = Http.Request("https://world.openfoodfacts.org/api/v0/product/737628064502.json")
let samples = Json.Parse(response.Body.ToString())
What i want to do is this:
Which in c# would be something like this:
public static Models.Product UpdateFromRemote(this Models.Product Product, string Language, string Barcode)
{
//the f# code included above to fetch the remote source
//only the url is fetched from:
// string.Format("https://{0}.openfoodfacts.org/api/v0/product/{1}.json",Language,Barcode);
Product.Title = samples.Product.GenericName; //samples is the fetched resource from the f# code
return Product;
}
What would be the logic in f#?
Currently i have this ( which is not correct/complete yet)
namespace LookupByBarcode.openfoodfacts.fSharp
open FSharp.Data
type model(Language,Barcode) =
member this.Language = Language
member this.Barcode = Barcode
module getRemote =
type json = JsonProvider<"example.json">
let response = json.Load("https://world.openfoodfacts.org/api/v0/product/737628064502.json")
let Title = response.Product.ProductNameEn
Upvotes: 0
Views: 103
Reputation: 243061
If you have an external DLL that you cannot modify that defines a type Product
, then there is no easy way of adding new fields to the product. I think the most elegant F# way of doing this would be to wrap it in a record that adds the additional information:
type MyProduct =
{ Product : Product
Language : string
Barcode : string }
Next, if you want to update a MyProduct
value so that it reflects a newly obtained title, then it depends on what the underlying Product
type looks like. Is it mutable or immutable?
To get idiomatic F# code, you would want to create a function that returns a clone. This is easy to do with F# records, but might be hard with C# objects. It might look something like this:
let updateProduct newTitle newLanguage myproduct =
// Create a new `Product` with changed title. If you want to avoid mutation,
// you need to create a new instance, which might be tedious for C# objects
let op = myproduct.Product
let np =
Product
(Title = newTitle, OtherThing = op.OtherThing,
YetAnotherThing = op.YetAnotherThing)
// Now create a new updated F# record - this is much easier
{ myprodcut with Product = np; Language = newLanguage }
Working idiomatically with C# mutable objects in F# will be tricky, so my recommendation would be to define the domain model in F#, which will let you use the nice F# with
keyword everywhere. That said, it might also make sense to just mutate the C# object - if that's what you really want to do.
Upvotes: 3