My understanding is that F# records are non-sealed classes. if so, can I inherit a record type? For example:
type person = {name:string; address:string}
type employee inherit person = {employeeId: string}
I have searching around the MSDN docs and language specs and I am not having any luck.
Thanks in advance
F# records cannot be inherited - as Matthew mentions, they are compiled to sealed classes, but it is also an aspect of the F# types system which simply does not allow this.
In practice, you could go with an ordinary class declaration. This means that you won't be able to use the { person with ... } syntax and you won't get the automatic structural equality, but it might make sense if you want to create C#-friendly code:
type Person(name:string) =
member x.Name = name
type Employee(name:string, id:int) =
inherit Person(name)
member x.ID = id
I think the preferred option would be to use composition rather than inheritance and make employee a record that is composed of some personal information and ID:
type PersonalInformation = { Name : string }
type Employee =
{ Person : PersonalInformation
ID : int }
I probably would not make a person a part of employee (that does not feel right to me, but that is just an intuition), which is why I renamed it to PersonalInformation here.
I suppose another option would be to have IPerson as an interface and have a record Employee implementing the interface:
type IPerson =
abstract Name : string
type Employee =
{ ID : int
Name : string }
interface IPerson with
member x.Name = x.Name
Which one is the best really depends on the concrete thing that you're modelling. But I think interfaces and composition are generally preferred in F# :-)
They are sealed classes, here's the first few lines of the class that's generated for person:
[CompilationMapping(SourceConstructFlags.RecordType)]
[Serializable]
public sealed class person
: IEquatable<person>,
IStructuralEquatable,
IComparable<person>,
IComparable,
IStructuralComparable
In addition to the answer from Thomas, the F# documentation suggests to consider discriminated unions instead of inheritance:
When you are creating object hierarchies, consider using a
discriminated union instead of inheritance. Discriminated unions can
also model varied behavior of different objects that share a common
overall type. A single discriminated union can often eliminate the
need for a number of derived classes that are minor variations of each
other.
See https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/inheritance#alternatives-to-inheritance
Reasons to avoid abstract classes are
The design principle "favor composition over inheritance"
That Domain Driven Design does not like things which do not exist in the real world.
Some example code how a User can be modelled:
type PersonalInformation = {
Name: string }
type EmployeeId = EmployeeId of string
type GuestId = GuestId of string
type EmployeeData = {
Id: EmployeeId
PersonalInformation: PersonalInformation }
type GuestData = {
Id: GuestId
PersonalInformation: PersonalInformation }
type User =
| Employee of EmployeeData
| DisabledEmployee of EmployeeData
| Guest of GuestData
Another example with 2 hierarchy levels of discriminated unions:
type EnabledUser =
| Employee of EmployeeData
| Guest of GuestData
type DisabledUser =
| DisabledEmployee of EmployeeData
| DisabledGuest of GuestData
type User =
| EnabledUser of EnabledUser
| DisabledUser of DisabledUser
Related
is there a way for an mvc model to have a property that is of f# option type and have it bind to the model during Post (just like the nullable properties currently map, but instead of null/value it would be F#'s Some and None)?
Sample f# model:
[<CLIMutableAttribute>]
type Student = { StudentId : int; MainSportsId : int option}
Then in the controller post method:
[<HttpPost>]
member this.AddRecord(resp: Student) =
resp.MainSportsId
Where resp.MainSportsId would be "Some number" if the user entered a number in the textbox or "None" if the textbox was empty.
Thank you!
Let's say I have an interface IEvent. This interface has an Id property which I have implemented in C# using:
public abstract class EventBase : IEvent
{
public Guid Id { get; protected set; }
]
Is there a way to inherit this abstract class in a F# record?
something like:
type OneOfMyEvents = {Id: Guid, Prop: string}
inherit EventBase(Id)
The problem is that I want to define all my events as records because it is really convenient but I also want to force all my events to have an Id property that I don't have to type every time.
Records can't inherit from classes, but they can implement interfaces. For example, using your IEvent interface:
open System
[<Interface>]
type IEvent =
abstract Id : Guid with get
type MyRecord = {
Id: Guid;
Prop: string;
} with
interface IEvent with
member this.Id
with get () = this.Id
No.
There is no syntax for specifying records inheriting from anything.
Record types in f# are distinct from class types. Inheritance from classes to records wouldn't make sense: records have structural equality semantics whereas classes (typically) have reference equality semantics. Inheritance might thus imply transitioning from the former to the latter as one descends the inheritance hierarchy, violating our expectation of is-a relationship between sub- and super-class (record?).
According to the documentation, records can be defined like this:
[ attributes ]
type [accessibility-modifier] typename = {
[ mutable ] label1 : type1;
[ mutable ] label2 : type2;
...
}
member-list
While you can add attributes and members to it, you can't derive it from a base class.
force all my events to have an Id property that I don't have to type every time
OK, but, what's easier to type?
Id: Guid
or
inherit EventBase(Id)
The record syntax is actually more succinct in this case.
I am using ASP.NET MVC2 and Entity Framework. I am going to simplify the situation a little; hopefully it will make it clearer, not more confusing!
I have a controller action to create address, and the country is a lookup table (in other words, there is a one-to-many relationship between Country and Address classes). Let's say for clarity that the field in the Address class is called Address.Land. And, for the purposes of the dropdown list, I am getting Country.CountryID and Country.Name.
I am aware of Model vs. Input validation. So, if I call the dropdown field formLand - I can make it work. But if I call the field Land (that is, matching the variable in Address class) - I am getting the following error:
"The parameter conversion from type
'System.String' to type 'App.Country'
failed because no type converter can
convert between these types."
OK, this makes sense. A string (CountryID) comes from the form and the binder doesn't know how to convert it to Country type. So, I wrote the converter:
namespace App {
public partial class Country {
public static explicit operator Country(string countryID) {
AppEntities context = new AppEntities();
Country country = (Country) context.GetObjectByKey(
new EntityKey("AppEntities.Countries", "CountryID", countryID));
return country;
}
}
}
FWIW, I tried both explicit and implicit. I tested it from the controller - Country c = (Country)"fr" - and it works fine. However, it never got invoked when the View is posted. I am getting the same "no type converter" error in the model.
Any ideas how to hint to the model binder that there is a type converter?
Thanks
A type converter is not the same as an explicit or implicit conversion, it's an object that converts values between various types.
I think you need to create a class inherited from TypeConverter that converts between Country and other types, and apply the TypeConverterAttribute to your class to specify the converter to use :
using System.ComponentModel;
public class CountryConverter : TypeConverter
{
// override CanConvertTo, CanConvertFrom, ConvertTo and ConvertFrom
// (not sure about other methods...)
}
[TypeConverter(typeof(CountryConverter))]
public partial class Country
{
...
}
Using interfaces is a very easy way to remove dependencies, but what happens when one of your classes needs a method not defined by the interface? If you're using constructor injection or a factory, how do you access that extra method without casting? Is this possible?
Here is an example of a factory with this problem. Am I trying to do something impossible? Thanks for your help.
interface IFoo {
int X { get; set; }
int Y { get; set; }
}
public class A : IFoo {
int X { get; set; }
int Y { get; set; }
}
public class B : IFoo {
int X { get; set; }
int Y { get; set; }
int Z { get; set; }
}
public static class FooFactory {
public static IFoo GetFoo(string AorB) {
IFoo result = null;
switch (AorB) {
case "A":
result = new A();
break;
case "B":
result = new B();
break;
}
return result;
}
}
public class FooContainer {
private IFoo foo;
public FooContainer(IFoo foo) {
this.foo = foo;
}
/* What methods would you define here. I'm new to IoC. */
}
public class Main(...) {
int x,y,z;
IFoo fooA = FooFactory.GetFoo("A");
x = foo.X;
y = foo.Y;
IFoo fooB = FooFactory.GetFoo("B");
x = foo.X;
y = foo.Y;
z = foo.Z; /* Does not compile */
z = ((B)foo).Z; /* Compiles, but adds unwanted dependency */
}
You do indeed need to cast. This is normal, and sometimes necessary. It is usually a sign that something is wrong though.
The ideal is that if a method/routine takes/returns an interface, then your logic only cares about the members exposed by that interface. If inside that method you find yourself checking the exact type so that you can cast to that type and call different members depending on the type, then something probably be wrong.
Let's say you have an IContact interface, and some of your entities that implement this are your classes Customer, Purchaser, and Contractor. If you have a SendChristmasCard method that takes IContact, it should only care about the IContact members. If you have logic inside this method that is doing a select Case on the obj.GetType().ToString to find out if it's a Customer or not, then:
That functionality should probably be over in the Customer-centric side of your code base, taking a Customer object as a parameter. (In your example, there would be separate logic for acting upon class A and class B.)
IContact should define common members that your SendChristmasCard method would call, and be completely ignorant of the logic that goes on inside the particular object. Each class that implements IContact would implement these member differently. (In your example, class A would also implement property B, but it wouldn't do anything with it.)
In the case where a method returns an interface and you use the object, the above still applies but in my experience it can, now and then, be best to put up with the casting. The complication you add by "fixing" the situation might make it more complicated. I would say that the further up and non-standard the logic is, just take the simple way out. SendChristmasCard is obviously not core functionality; and if an IContact factory method is only handy method that gives you All the contacts, then maybe just use that, pass it to SendChristmassCard(IContact Contact), and inside there check for the type to say "it was great buying from you this year" or "it was great selling to you this year" etc. But if this is core logic in your system, you really need to look for a better way.
Check out the Decorator Pattern though, which can help in situations like this.
When you encounter the need to downcast an object, it is usually a sign that the API could be better.
Downcasting an abstract type is a violation of the Liskov Substitution Principle. It can usually best be addressed by changing the style of the interface in question. Instead of exposing a lot of properties and queries (in CQS terminology), reverse the focus towards a more command-oriented approach. This is the Hollywood Principle.
Instead of having IFoo expose the X and Y properties, you may be able to redefine its behavior towards a set of commands:
public interface IFoo
{
void DoStuff();
void DoSomethingElse(string bar);
void DoIt(DateTime now);
}
Concrete implementations can then encapsulate whatever data they would like (such as X, Y or Z properties) without the consumer needing to know about them.
When the interface grows to become too big, it's time to apply the Interface Segregation Principle or the Single Responsibility Principle.
If you're trying to access a method that isn't available to the interface, then don't use the Factory. You're obviously hard coding a dependency...so just go with it (but only if it's really necessary).
No need to over-complicate things.
Trying to cast back to an Object type rather than the interface is going to introduce a dependency...but it's going to hide it rather than obviously expose the dependency. If somebody changes the Factory in the future and your call returns a different Object type, your code is now going to break in a non-obvious way.
Let's say I have two tables employee and salary with a 1:N relationship (one salary can be associated with many employees).
In plain SQL the tables would be joined with:
SELECT e.id, e.name, s.salary FROM employee e, salary s WHERE s.id = e.salary_id AND e.id = 12345;
Assuming the following GORM-powered domain class how do I map the legacy database structure to the class?
class Employee {
String name
int salary
}
Clarification #1: I want only one domain class containing data from both tables. Adding another class is hence not an option.
Clarification #2: The question I'm trying to find an answer to is simply "how do I map two tables to one class using Grails/GORM"? If you believe that it is impossible to do so, then please state that clearly in your answer rather than trying to restate the question.
IMO it is not possible with plain Grails/GORM to join multiple tables and map them to one Domain class. As a workaround you could use a legacy XML hibernate mapping and leverage the join feature to achieve your desired goal. Of course you would loose a lot of the GORM goodies.
Your SQL example indicates there are two tables, Employee and Salary. This should also be reflected in your classes. So instead of one, you need two classes. The GORM mapping would then look like this.
class Employee {
String name
Salary salary
}
class Salary {
static hasMany = [ employees : Employee ]
int salary
}
See http://www.grails.org/GORM+-+Defining+relationships
You could, instead of having salary and name as properties, have them as get* methods that actually run a query on both these tables.
granted, that isnt the grails way, and its strongly recommended that you do follow the grails way.
I don't fully understand the limitation on not being able to add another class if there are 2 tables in the database, but if you're looking to have a unified interface, would it work to delegate the methods to the Salary class?
Something like:
class Salary {
int amount
}
class Employee {
Salary _salary
String name
String toString() { name }
public Integer getSalary() {
return _salary?.amount
}
public void setSalary(Integer amount) {
// not quite sure of your business logic here, this is a guess
_salary = Salary.findByAmount(amount)
if (!_salary) {
_salary = new Salary(amount: amount)
_salary.save()
}
}
}
def e = new Employee(name:"willy loman", salary: 100)
e.save()
assert e.salary == 100
It's also possible that you might be able to make what you're asking for work with a custom hibernate mapping file, but I'm not familiar enough with contorting hibernate in that manner to say for sure.
See the Custom User Type section of this page.