I have a syntax problem: I would like to put a condition in my controller. In C#, my condition is: if (Request.Files["FileUpload"].ContentLength > 0)
I can't succeed to translate in F#, any suggestions?
My code:
namespace FsWeb.Controllers
open System.Web.Mvc
open System
open System.Web
[<HandleError>]
type HFAnalysisController() =
inherit Controller()
member this.HFAnalysis () =
this.View() :> ActionResult
member this.Importexcel() =
// C# // if (Request.Files["FileUpload1"].ContentLength > 0)
I suspect the question is about how to get a dictionary value. In F# indexed properties can't be called the same way as in C#. The Item[] member has to be called explicitly:
this.Request.Files.["FileUpload1"].ContentLength
and you could write something like:
member this.ImportExcel() =
if this.Request.Files.["FileUpload1"].ContentLength > 0 then
...
Related
I've been revisiting one of my old experiments. The code below is a file I added to Daniel Mohl's F# MVC5 project which I created in Visual Studio 2015. It compiled and worked in VS2015 (and still does) but when I try to compile it in VS2019 I get an error message on the |> this.View lines towards the end: "FS0405: A protected member is called or 'base' is being used. This is only allowed in the direct implementation of members since they could escape their object scope". Does anyone have any idea what I need to do to get rid of the error
namespace fsmvcproject.Models
open System
open System.ComponentModel.DataAnnotations
type Newarticle() =
[<Key>]member val Id = 0 with get, set
member val Headline = "" with get, set
member val Author = "" with get, set
member val Publication = "" with get, set
member val Intro = "" with get, set
member val Story = "" with get, set
namespace fsmvcproject.Repositories
open System.Data.Entity
open fsmvcproject.Models
open System.Collections.Generic
type SGdbEntities() =
inherit DbContext("Data Source=127.0.0.1\SQLEXPRESS;Persist Security Info=True;Initial Catalog=SG;User ID=xxxx;Password=xxxx")
[<DefaultValue()>] val mutable newarticles : IDbSet<Newarticle>
member x.Newarticles with get() = x.newarticles and set v = x.newarticles <- v
type NewarticlesRepository() =
member x.GetAll () =
use context = new SGdbEntities()
query { for a in context.Newarticles do
sortByDescending a.Id
select a }
|> Seq.toList
member x.GetDetail (id) =
use context = new SGdbEntities()
query { for a in context.Newarticles do
where (a.Id = id)
select a }
|> Seq.toList
namespace fsmvcproject.Controllers
open fsmvcproject.Repositories
open System.Web.Mvc
[<HandleError>]
type ArticlesController(repository :NewarticlesRepository) =
inherit Controller()
new() = new ArticlesController(NewarticlesRepository())
member this.Index () =
repository.GetAll()
|> this.View
member this.Detail (id) =
repository.GetDetail(id)
|> this.View
I think the problem here is that View is a protected method, which means that you can call it directly from your derived class, but you can't treat it like a first-class F# function.
Thus, to fix the compiler error, try changing model |> this.View to this.View(model).
How do I implement an F# high order function in C#?
public ICommand RequestAccount =
new DelegateCommand(FuncConvert.ToFSharpFunc( _ => Debug.WriteLine() ),
FuncConvert.ToFSharpFunc( _ => return true )
);
Error CS0411 The type arguments for method
'FuncConvert.ToFSharpFunc(Action)' cannot be inferred from the
usage. Try specifying the type arguments explicitly.
Based on the error, I'm not aware of how to express the type parameters explicitly. Hence, I don't think C# understands what a unit is that's to be returned on the first lambda.
DelegateCommand
type DelegateCommand (action:(obj -> unit), canExecute:(obj -> bool)) =
let event = new DelegateEvent<EventHandler>()
interface ICommand with
[<CLIEvent>]
member this.CanExecuteChanged = event.Publish
member this.CanExecute arg = canExecute(arg)
member this.Execute arg = action(arg
If you are in control of both the C# and the F# part of the code, then I would not try to create F# functions explicitly from C# - that will just make your C# code ugly. You can easily add a static method that will take Func and Action delegates and provide a C#-friendly interface:
type DelegateCommand (action:(obj -> unit), canExecute:(obj -> bool)) =
let event = new DelegateEvent<EventHandler>()
interface ICommand with
[<CLIEvent>]
member this.CanExecuteChanged = event.Publish
member this.CanExecute arg = canExecute(arg)
member this.Execute arg = action(arg)
static member Create(action:Action<obj>, canExecute:Func<obj, bool>) =
DelegateCommand(action.Invoke, canExecute.Invoke)
Now you can use DelegateCommand.Create from C# in a nice way:
DelegateCommand.Create(
(o => Console.WriteLine(o)),
(o => true) )
For the record, I also do not quite see the value of defining DelegateCommand in F# and using that from C# if you are not doing anything else on the F# side - it seems like a simple type that could as well be defined in C# (i.e. you are not gaining much by doing that in F#).
Try to explicitly specify the arguments type
public ICommand RequestAccount =
new DelegateCommand(FuncConvert.ToFSharpFunc<object>(obj => Debug.WriteLine(obj)),
FuncConvert.ToFSharpFunc<object, bool>(_ => true));
I'm currently rewriting a graduate student project that was written in c# to f#.
I'm stumped on how to handle IRepository interfaces in f#. It seems trivial in c#, but f# doesn't like what I've done.
The IRepository in question is defined in the myNameSpace.SolarSystem name space. Which I make sure to include in my f# project.
Here are my notes:
f# - invalid use of an interface type <--(let repo = IRepository<SolarSystem>())
open myNameSpace.SolarSystem
let searchCatalog = [| 8; 11; 31 |]
let repo = IRepository<SolarSystem>()
let ClassOfSolarSystems classOfStar =
repo.Query().Where(fun s -> s.SolarGroups.Any(fun c -> searchCatalog.Contains(classOfStar) ))
c# - no error:
using myNameSpace.SolarSystem
private readonly int[] searchCatalog = new int[] { 8, 11, 31 };
public IRepository<SolarSystem> Repo { get; set; }
public IEnumerable<SolarSystem> ClassOfSolarSystems(Int32 classOfStar)
{
return Repo.Query()
.Where(s => s.SolarGroups.Any(c => searchCatalog.Contains(classOfStar)));
}
I exhausted my googlefu and could not find any meaningful(to me at least) solutions.
Is there a way to use IRepository interfaces in f#?
Thanks!
Your F# line is equivalent to this C#, as the keyword new is implicit in F#.
var repo = new IRepository<SolarSystem>()
The C# compiler would not let you do that either. Also, your C# example is a property, while in F# it is a value binding. To define properties in F# you need to use the member keyword.
Edit
I played around with the editor a bit until I found something the compiler was mildly happy about, came up with this.
let ClassOfSolarSystems (repo : IRepository<SolarSystem>) classOfStar =
repo.Query()
|> Seq.filter(fun s -> s.SolarGroups.Any(fun c -> searchCatalog.Contains(classOfStar) ))
I didn't mess too much with your LINQ expressions but you should consider using the F# Seq module instead.
When you write
let repo = IRepository<SolarSystem>()
you try to create an instance of the interface, as you well know, it is impossible.
Just create a function that takes a repository and search parameters.
open SolarSystems
open System.Linq
type RepositoryFunctions =
member this.ClassOfSolarSystems (repo:IRepository<SolarSystem>) (classOfStar:int32) =
repo.Query().Where(fun s -> s.SolarGroups.Any(fun c -> searchCatalog.Contains(classOfStar) ))
So, if you not prefer to use LINQ in F#, you can write:
open SolarSystems
type RepositoryFunctions =
member this.ClassOfSolarSystems (repo:IRepository<SolarSystem>) (classOfStar:int32) =
let catalogContainsStar searchCatalog = searchCatalog.Contains(classOfStar)
let systemContainsStar solarSys = solarSys.SolarGroups.Any( catalogContainsStar )
let getAllWithStar = Seq.filter systemContainsStar
in
repo.Query() |> getAllWithStar
I have written a class in F# implementing an interface in order to build a C#-friendly interface for my F#-assembly.
I have written some of the properties as indexed properties. However, when I try to use the type from C#, I only get the synthetic get_PropertyName methods in intellisense and the compiler likewise complains in case I want to use the indexed properties like I would do for C# ones.
Code for reference:
type IMyInterfaceType =
abstract MyProperty : MyType1 with get
abstract MyIndexedProperty : MyType2 -> MyType3 with get
abstract MyTwoDimensionalIndexedProperty : (MyType4 * MyType5) -> MyType6 with get
type MyInterfaceType =
new () = { }
interface IMyInterfaceType with
member this.MyProperty with get () = new MyType1 ()
member this.MyIndexedProperty with get parameter = new MyType3 ()
member this.MyTwoDimensionalIndexedProperty with get pair = new MyType6 ()
When trying to access this class from C#, I only get methods
get_MyIndexedProperty(MyType2 parameter)
get_MyTwoDimensionalIndexedProperty(Tuple<MyType4, MyType5>)
instead of the indexed properties I had hoped for.
Am I doing something wrong or is this a known issue?
cheers
--Mathias.
Response to the original question:
Indexer properties in C# have special name Item thus to create indexer accessible from C# you must name your indexer property "Item", e.g.:
type X () =
member this.Item with get key = ....
Now it can be accessed both in F# using (x : X).[key] or in C# using x[key] .
Response to the updated question:
C# does not support indexed properties the way F# does. Instead using additional type is advised: https://msdn.microsoft.com/en-us/library/aa288464%28v=vs.71%29.aspx
So you can try to use something like this:
[<AbstractClass>]
type Indexer<'index, 'result> () =
abstract Get : 'index -> 'result
member this.Item with get key = this.Get key
type IMyInterfaceType =
abstract MyProperty : MyType1 with get
// F# indexed propetties
abstract MyIndexedProperty : MyType2 -> MyType3 with get
// C# workaround
abstract MyCSharpIndexedProperty : Indexer<MyType2, MyType3> with get
type MyInterfaceType () as this =
let proxy =
{ new Indexer<MyType2, MyType3> () with
member __.Get key = (this :> IMyInterfaceType).MyIndexedProperty key }
interface IMyInterfaceType with
member __.MyProperty with get () = new MyType1 ()
member __.MyIndexedProperty with get key = new MyType3 ()
member __.MyCSharpIndexedProperty with get () = proxy
And two dimensional property similarly by creating Indexer<'index1, 'index2, 'result> () = ...
I hit something new to me with the following piece of code when following the equivalent in C# here. The compiler gives multiple errors basically telling the IConnectableObservable created in source.Publish() does not match IObservable even though it derives from it (according to the MSDN article linked).
Is there something in F# that is different with regard to C# concerning inheritance in this case or can someone provider pointers as to what is going on? Have I just made a typo I can't see? What comes to the heading regarding covariance, it's just a wild guess as I'm at least temporarily out of ideas. And so, maybe writing somewhere may help me and others...
One example of the many error messages:
No overloads match for method 'Create'. The available overloads are shown below (or in the Error List window).
No overloads match for method 'Switch'. The available overloads are shown below (or in the Error List window).
Error Possible overload: '(extension) IObservable.Switch<'TSource>() :
IObservable<'TSource>'. Type constraint mismatch. The type
IObservable<IConnectableObservable<'b>> is not compatible with type
IObservable<IObservable<'a>> The type 'IObservable<'a>' does not match the type 'IConnectableObservable<'b>'.
open System.Reactive.Concurrency
open System.Reactive.Disposables
open System.Reactive.Subjects
open System.Reactive.Linq
type Observable with
static member inline Suspendable(source: IObservable<_>, suspend: IObservable<bool>, isSuspendedInitially: bool): IObservable<_> =
Observable.Create<_>(fun observer ->
let shared = source.Publish()
let pausable =
suspend.StartWith(isSuspendedInitially)
.TakeUntil(shared.LastOrDefaultAsync())
.DistinctUntilChanged()
.Select(fun p -> if p then shared else Observable.Empty<_>())
.Switch()
new CompositeDisposable(pausable.Subscribe(observer), shared.Connect()))
The corresponding C# code
public static class RxExtensions
{
public static IObservable<T> Suspendable<T>(this IObservable<T> stream, IObservable<bool> suspend, bool isSuspendedInitially)
{
return Observable.Create<T>(o =>
{
var shared = stream.Publish();
var pausable = suspend
.StartWith(isSuspendedInitially)
.TakeUntil(shared.LastOrDefaultAsync())
.DistinctUntilChanged()
.Select(p => p ? shared : Observable.Empty<T>())
.Switch();
return new CompositeDisposable(pausable.Subscribe(o), shared.Connect());
});
}
}
This was a bit tricky, but you need to add two upcasts: shared to IObservable<_>, and the result of the lambda function to IDisposable. These would be implicit in C#, but need to be explicit in F#:
type Observable with
static member inline Suspendable (source: IObservable<_>,
suspend: IObservable<bool>,
isSuspendedInitially: bool): IObservable<'a> =
Observable.Create<_>(fun observer ->
let shared = source.Publish()
let pausable =
suspend.StartWith(isSuspendedInitially)
.TakeUntil(shared.LastOrDefaultAsync())
.DistinctUntilChanged()
.Select(fun p -> if p then shared :> IObservable<_>
else Observable.Empty<_>())
.Switch()
new CompositeDisposable(pausable.Subscribe(observer),
shared.Connect()) :> IDisposable)