Do functional generics exist and what is the correct name for them if they do?

Consider the following generic class:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public class EntityChangeInfo<EntityType,TEntityKey>
{
ChangeTypeEnum ChangeType {get;}
TEntityKeyType EntityKey {get;}
}
</code>
<code>public class EntityChangeInfo<EntityType,TEntityKey> { ChangeTypeEnum ChangeType {get;} TEntityKeyType EntityKey {get;} } </code>
public class EntityChangeInfo<EntityType,TEntityKey>
{
    ChangeTypeEnum ChangeType {get;}
    TEntityKeyType EntityKey {get;}
}

Here EntityType unambiguously defines TEntityKeyType.
So it would be nice to have some kind of types’ map:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public class EntityChangeInfo<EntityType,TEntityKey> with map
< [ EntityType : Person -> TEntityKeyType : int]
[ EntityType : Car -> TEntityKeyType : CarIdType ]>
{
ChangeTypeEnum ChangeType {get;}
TEntityKeyType EntityKey {get;}
}
</code>
<code>public class EntityChangeInfo<EntityType,TEntityKey> with map < [ EntityType : Person -> TEntityKeyType : int] [ EntityType : Car -> TEntityKeyType : CarIdType ]> { ChangeTypeEnum ChangeType {get;} TEntityKeyType EntityKey {get;} } </code>
public class EntityChangeInfo<EntityType,TEntityKey> with map 
  < [ EntityType : Person -> TEntityKeyType : int]
    [ EntityType : Car -> TEntityKeyType : CarIdType ]>
{
    ChangeTypeEnum ChangeType {get;}
    TEntityKeyType EntityKey {get;}
}

Another one example is:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code> public class Foo<TIn> with map
< [TIn : Person -> TOut1 : string, TOut2 : int, ..., TOutN : double ]
[TIn : Car -> TOut1 : int, TOut2 :int, ..., TOutN : Price ] >
{
TOut1 Prop1 {get;set;}
TOut2 Prop2 {get;set;}
...
TOutN PropN {get;set;}
}
</code>
<code> public class Foo<TIn> with map < [TIn : Person -> TOut1 : string, TOut2 : int, ..., TOutN : double ] [TIn : Car -> TOut1 : int, TOut2 :int, ..., TOutN : Price ] > { TOut1 Prop1 {get;set;} TOut2 Prop2 {get;set;} ... TOutN PropN {get;set;} } </code>
 public class Foo<TIn> with map
< [TIn : Person -> TOut1 : string, TOut2 : int, ..., TOutN : double ]
  [TIn : Car -> TOut1 : int, TOut2 :int, ..., TOutN : Price ] >
    {
        TOut1 Prop1 {get;set;}
        TOut2 Prop2 {get;set;}
        ...
        TOutN PropN {get;set;}
    }

The reasonable question: how can this be interpreted by the compiler?
Well, for me it is just the shortcut for two structurally similar classes:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public sealed class Foo<Person>
{
string Prop1 {get;set;}
int Prop2 {get;set;}
...
double PropN {get;set;}
}
public sealed class Foo<Car>
{
int Prop1 {get;set;}
int Prop2 {get;set;}
...
Price PropN {get;set;}
}
</code>
<code>public sealed class Foo<Person> { string Prop1 {get;set;} int Prop2 {get;set;} ... double PropN {get;set;} } public sealed class Foo<Car> { int Prop1 {get;set;} int Prop2 {get;set;} ... Price PropN {get;set;} } </code>
public sealed class Foo<Person>
{
    string Prop1 {get;set;}
    int Prop2 {get;set;}
    ...
    double PropN {get;set;}
}

public sealed class Foo<Car>
{
    int Prop1 {get;set;}
    int Prop2 {get;set;}
    ...
    Price PropN {get;set;}
}

But besides this we could imaging some update of the Foo<>:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public class Foo<TIn> with map
< [TIn : Person -> TOut1 : string, TOut2 : int, ..., TOutN : double ]
[TIn : Car -> TOut1 : int, TOut2 :int, ..., TOutN : Price ] >
{
TOut1 Prop1 {get;set;}
TOut2 Prop2 {get;set;}
...
TOutN PropN {get;set;}
public override string ToString()
{
return string.Format("prop1={0}, prop2={1},...propN={N-1},
Prop1, Prop2,...,PropN);
}
}
</code>
<code>public class Foo<TIn> with map < [TIn : Person -> TOut1 : string, TOut2 : int, ..., TOutN : double ] [TIn : Car -> TOut1 : int, TOut2 :int, ..., TOutN : Price ] > { TOut1 Prop1 {get;set;} TOut2 Prop2 {get;set;} ... TOutN PropN {get;set;} public override string ToString() { return string.Format("prop1={0}, prop2={1},...propN={N-1}, Prop1, Prop2,...,PropN); } } </code>
public class Foo<TIn> with map
    < [TIn : Person -> TOut1 : string, TOut2 : int, ..., TOutN : double ]
      [TIn : Car -> TOut1 : int, TOut2 :int, ..., TOutN : Price ] >
        {
            TOut1 Prop1 {get;set;}
            TOut2 Prop2 {get;set;}
            ...
            TOutN PropN {get;set;}

            public override string ToString()
            {
                 return string.Format("prop1={0}, prop2={1},...propN={N-1},
                                         Prop1, Prop2,...,PropN);
            }
        }

This all can seem quite superficial but the idea came when I was designing the messages for our system. The very first class. Many messages with the same structure should be discriminated by the EntityType.

So the question is whether such construct exists in any programming language?

5

Yes, this facility does exist in some programming languages.

For example, in Haskell, these are called Functional Dependencies (fundeps are not part of Haskell 98, but they are supported in common implementations like GHC)

In C++, you can achieve this kind of thing with traits classes.

Well…you could just close the types for convenience:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public class EntityChangeInfo<TEntityType,TEntityKey>
{
ChangeTypeEnum ChangeType {get;}
TEntityKeyType EntityKey {get;}
}
public class PersonChangeInfo : EntityChangeInfo<Person,int>
{
}
public class CarChangeInfo : EntityChangeInfo<Car, CarIdType>
{
}
</code>
<code>public class EntityChangeInfo<TEntityType,TEntityKey> { ChangeTypeEnum ChangeType {get;} TEntityKeyType EntityKey {get;} } public class PersonChangeInfo : EntityChangeInfo<Person,int> { } public class CarChangeInfo : EntityChangeInfo<Car, CarIdType> { } </code>
public class EntityChangeInfo<TEntityType,TEntityKey>
{
    ChangeTypeEnum ChangeType {get;}
    TEntityKeyType EntityKey {get;}
}

public class PersonChangeInfo : EntityChangeInfo<Person,int>
{
}

public class CarChangeInfo : EntityChangeInfo<Car, CarIdType>
{
}

Though, it seems something like this would be more flexible:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public **interface** IEntityChangeInfo<TEntity,TEntityKey>
{
ChangeTypeEnum ChangeType {get;}
TEntityKey EntityKey {get;}
TEntity Entity {get;}
}
</code>
<code>public **interface** IEntityChangeInfo<TEntity,TEntityKey> { ChangeTypeEnum ChangeType {get;} TEntityKey EntityKey {get;} TEntity Entity {get;} } </code>
public **interface** IEntityChangeInfo<TEntity,TEntityKey>
{
    ChangeTypeEnum ChangeType {get;}
    TEntityKey EntityKey {get;}
    TEntity Entity {get;}
}

Also, this might be language dependent but I would suggest that even if you use an enum internally for convenience, you NOT expose the enum in the contract.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public **interface** IEntityChangeInfo<TEntity,TEntityKey>
{
int? ChangeTypeId {get;}
TEntityKey EntityKey {get;}
TEntity Entity {get;}
}
</code>
<code>public **interface** IEntityChangeInfo<TEntity,TEntityKey> { int? ChangeTypeId {get;} TEntityKey EntityKey {get;} TEntity Entity {get;} } </code>
public **interface** IEntityChangeInfo<TEntity,TEntityKey>
{
    int? ChangeTypeId {get;}
    TEntityKey EntityKey {get;}
    TEntity Entity {get;}
}

or

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public **interface** IEntityChangeInfo<TEntity,TEntityKey,TChangeType>
{
TChangeType ChangeType {get;}
TEntityKey EntityKey {get;}
TEntity Entity {get;}
}
</code>
<code>public **interface** IEntityChangeInfo<TEntity,TEntityKey,TChangeType> { TChangeType ChangeType {get;} TEntityKey EntityKey {get;} TEntity Entity {get;} } </code>
public **interface** IEntityChangeInfo<TEntity,TEntityKey,TChangeType>
{
    TChangeType ChangeType {get;}
    TEntityKey EntityKey {get;}
    TEntity Entity {get;}
}

4

John Bartholomew’s answer is the correct exposition of the technique you’re referring to.

Leaving this incorrect answer here for a short while for posterity as it’s relevant related content. Will probably delete tomorrow when you’ve had time to review the information in case it’s valuable to you 🙂


There are a class of functional languages with a related concept, referred to as “dependent types” the idea being you can create functionality that depends on particular values of a type rather than just the type itself.
(that is my very limited description of the concept; crazy math-nuts people can speak to this more)

Here’s the wikipedia for some further reading, it lists a hand full of languages which implement dependent types.

One of the biggest uses of dependent types as I understand them is for proofs, which makes sense if you think about it and is similar to what you’re trying to use it for; you’re trying to constrain the types to get specific functionality in your type out of a type passed to you; dependent types works similarly but constraining down to the value level which is a very hardy constraint you could see being useful in the context of proving things are interacting in a strictly defined way.

Please; anyone more familiar with the concept of dependent types correct me if I’m off in my understanding. It’s a very high level concept and not one I’ve direct experience with beyond my addiction to reading about various languages, I wouldn’t want to be giving incorrect information here.

6

I think you are using generics for something that they were not intended and designed for.

Generics are to allow caller to create specific type from generic pattern. The generic type should never know what type caller will put in. It can limit those types, but never know exact types. Think how would you use those types? You cannot pass this to anything else, because it would mean this something else too needs to be generic and then you get “generic creep” where generic types get propagated through structure. I was there and it is not good at all.

What you are trying to achieve is extremely similar to code generation. You can use T4 or something and generate all required classes from some kind of definition. You should really forget about generics and think in pure OOP. Find something all those messages have in common that the message system can use and implement concrete class for each message type. This will make the design much more flexible, because you are not limited to two fields and will be much cleaner.

6

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật