F# - (NUnit ApplyTo) member matches multiple overloads ... please restrict it to one - f#

I'm trying to write custom equality constraint to compare 2 objects.
open FsUnit
open NUnit.Framework.Constraints
type equalCompany(expected:Company) =
inherit Constraints.EqualConstraint(expected)
override this.ApplyTo (actual:Company option) =
//actual.IsSome |> should equal True
//actual.Value.Id |> should equal expected.Id
ConstraintResult(this, actual, true)
// example of usage:
actualCompany |> should equalCompany expectedCompany
It complains because the ApplyTo implementation matches multiple overloads and I can't find the right syntax.
Ideally I like to compare to Company option but still just Company is fine.
The types involved are the following:
type CompanyType =
| Bank
| Exchange
type Company = {
Id: string
Types: CompanyType list
}
and I'm trying to write my equality constraint because the simple existing equal does not work properly with Types (the list, also if sorted, appears always different)
How can I properly override the ApplyTo function?

I think the issue is that the ApplyTo method that you are trying to override is generic and needs to have a signature ApplyTo<'T> : 'T -> ConstraintResult.
If I understand your code correctly, you are trying to define a comparison between Company and Company option. To Do this, you would need to check (at runtime) that the value passed to ApplyTo is of the right type. Then you can cast it and implement whatever logic you need.
Here is a minimal sample that worked for me, written as an F# script file:
#r "nuget: nunit"
#r "nuget: fsunit"
type Company(s) =
member x.Name = s
open FsUnit
open NUnit.Framework.Constraints
type equalCompany(expected:Company) =
inherit EqualConstraint(expected)
override this.ApplyTo<'T>(actual:'T) =
match box actual with
| :? option<Company> as co ->
ConstraintResult(this, actual,
co.IsSome && co.Value.Name = expected.Name)
| _ ->
ConstraintResult(this, actual, false)
let actualCompany = Company("Test")
let expectedCompany = Company("Test")
// This passes, because it has the right type
Some actualCompany |> should equalCompany expectedCompany
// This does not, because the 'ApplyTo' logic does not handle this type
actualCompany |> should equalCompany expectedCompany

Related

Entity Framework Core : Apply Conversion to all properties of type Option<T> in F#

I'm using Entity Framework Core 2.1 in F#.
I want to setup a generic type conversion for Option types so that EF knows how to handle them.
I found this very helpful post that shows how to setup a generic convertor for Option types.
So here's what I have so far (putting snippits together)
[<Table("Users", Schema = "pm")>]
type [<CLIMutable>] User = {
[<DatabaseGenerated(DatabaseGeneratedOption.Identity)>]
UserID : int64
FirstName : string
LastName : string
LastLoggedInTime : DateTimeOffset option
}
with
static member Configure (mb : ModelBuilder) =
mb.Entity<User>()
.Property(fun p -> p.LastLoggedInTime)
.HasConversion(OptionConverter<DateTimeOffset>()) |> ignore
This is great, except if I add a new property to my type. I will need to add the last three lines of the above code for that property as well. I'm looking for a way to do it for all properties all at once :D
So then I found this helpful SO answer that lead me to the below code
let tt = mb.Model.GetEntityTypes()
|> Seq.map(fun et -> et.GetProperties()) |> Seq.concat
|> Seq.filter(fun p -> p.ClrType = typeof<Option<DateTimeOffset>>)
|> Seq.map(fun p -> mb.Entity(p.DeclaringEntityType.ClrType)
.Property(p.Name)
.HasConversion(OptionConverter<DateTimeOffset>()))
Now the problem that I'm trying to solve is to figure out how to make this code work with Generic types so I don't have to specify the type. I want it to be something like p.ClrType = typeof<Option<T'>> and at the end, something like .HasConversion(OptionConverter<T'>())
Any thoughts?
so going off your initial question "I want to setup a generic type conversion for Option types so that EF knows how to handle them." I am assuming you mean you want EF to properly map an option to a "NULL" column of the corresponding base type, and that you are having problems because EF doesn't know how to handle FSharp.Option?
You could instead just use Nullable in place of Option for your EF types, and it will resolve as it does in C#.
So for instance, your example type becomes:
type [<CLIMutable>] User = {
[<DatabaseGenerated(DatabaseGeneratedOption.Identity)>]
UserID : int64
FirstName : string
LastName : string
LastLoggedInTime : Nullable<DateTimeOffset>
}
For types that can not be Nullable but are Options in your domain (strings for example), you just set them as their base type and it will work just fine.
If you are mapping to F# domain types somewhere else, you can just use Option.ToNullable and Option.OfNullable there, or map None to null if the type cannot be nullable as stated above.
Hope this helps!

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.

f# Statically resolved types in type members

I want to implement IEnumerable<KeyValuePair<DateTime, 'T>> in my own class and add math operators to that class so that the operators could work like inline function on any numeric types of 'T - automatically add constraints.
I just cannot make the following piece of code work. It doesn't work neither with nor without 'inline' keyword at the member declaration.
Also, if I define a function
let inline add l r = l + r
before the type and use it instead of addition l.Value + r.Value, it also doesn't work.
Could someone please show me what I am doing wrong?
Probably the whole approach is wrong and there is a way to achieve the same goal the other way?
namespace Test
open System
open System.Linq
open System.Collections.Generic
[<SerializableAttribute>]
type TimeSeries<'T>(dictionary : IDictionary<DateTime, 'T>) =
let internalList = new SortedList<DateTime, 'T>(dictionary)
interface IEnumerable<KeyValuePair<DateTime, 'T>> with
member this.GetEnumerator() = internalList.GetEnumerator()
member this.GetEnumerator() : Collections.IEnumerator
= internalList.GetEnumerator() :> Collections.IEnumerator
member private this.sl = internalList
static member inline (+) (left : TimeSeries<'T>, right : TimeSeries<'T>) =
let res =
query {
for l in left do
join r in right on
(l.Key = r.Key)
select (l.Key, l.Value + r.Value)
}
new TimeSeries<'T>(res |> dict)
Your approach seems correct to me.
The reason why your code doesn't compile is because F# type inference is inferring a static constraint (compile-time) for the type variable 'T which is the same used for the type definition.
A generic parameter of a type definition can't be statically resolved (no "hat" types) but nothing stops you from defining a function or a member which uses these compile-time constraints.
Just change your type variable 'T to 'U in the static member (+) definition and it will be fine.
Still you'll be allowed to create a TimeSeries instance of a type which does not support (+) (ie: TimeSeries<obj>) but you will not be able to use (+) for those instances, anyway if you do it you'll get a nice error message at compile-time.

F# mutable with no initial value for MEF

I have a bunch of modules that export an IModule interface. So in the main program I have no problems
...
let mutable modules = Seq.empty
[<ImportMany>]
member x.Modules
with get():IEnumerable<Lazy<IModule, IModuleData>> = modules
and set(a) = modules <- a
...
But now I need to expose an interface back to those modules. So each module will import a single interface
...
let mutable parent:IParent = ?
[<Import>]
member x.Parent
with get():IParent = parent
and set(a) = parent <- a
...
So my problem is how do I go about creating my mutable "parent" when I have no initial value for it? Also, is this the appropriate way to expose an API back to component parts?
Using Unchecked.defaultof<_> should do the trick, but it means that you're circumventing the F# type system, which may be a dangerous thing to do - the system tries to prevent you from accidentally dereferencing null values (and getting NullReferenceException).
Types that are declared in F# don't have null as a proper value, which is an attempt to eliminate the usual errors caused by null. The clean F# approach is to use option types to represent the fact that a value is missing:
let mutable parent:option<IParent> = None
[<Import>]
member x.Parent
with get():IParent =
match parent with
| Some p -> p
| None -> failwith "TODO: Throw some reasonable exception here!"
and set(a) = parent <- Some(a)
If you just want to say that IParent can have a null value (perhaps because you need to use it in some C# code that will ignore the F# restriction anyway), then you can mark the type definition using a special attribute that allows using null with the type.
[<AllowNullLiteral>]
type IParent =
abstract DoStuff : unit -> unit
Then you can write let mutable parent:IParent = null. The benefit of this approach is that you can also easily check whether a value is null (using just if parent <> null then ...) which is not that obvious when you use Unchecked.defaultof<_>.
let mutable parent = Unchecked.defaultof<IParent>
should do the trick.
Following up on what Tomas explained, you should probably put your imports directly into your constructor. That will allow your code to be a bit more idiomatic.

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