Mapping Haskell Concepts To C# 3

I have question on mapping some Haskell concepts to C# 3 ones. Maybe there are not any strict equivalents; yet it helps: 1 - What is the equivalent of "Type Constructor" in C#? 2 - What is the equivalent of "Data Constructor" in C#? 3 - What is the logical implementation of pattern matching in C#? (For example using structures with indicator fields or using interfaces and inheritance and dynamically dispatch in calling overloaded methods. Also this question contain a hidden one...GADTs!) Best Regards -- Kaveh Shahbazian email: kaveh.shahbazian@gmail.com

2008/5/17 Kaveh Shahbazian
I have question on mapping some Haskell concepts to C# 3 ones. Maybe there are not any strict equivalents; yet it helps:
1 - What is the equivalent of "Type Constructor" in C#?
Class declaration. Generic ones. E.g. List<int>, is a type where the type constructor List has been applied to the type int.
2 - What is the equivalent of "Data Constructor" in C#?
Constructors, I guess.
3 - What is the logical implementation of pattern matching in C#? (For example using structures with indicator fields or using interfaces and inheritance and dynamically dispatch in calling overloaded methods. Also this question contain a hidden one...GADTs!)
You can use an abstract base class, and then inherit one class for each constructor (e.g. base class Expression, and concrete subclasses Mul, Add, etc.). Then you can use runtime type reflection to figure out which kind of Expression you have and branch on it. -- Sebastian Sylvan +44(0)7857-300802 UIN: 44640862

On Sat, 2008-05-17 at 20:51 +0100, Sebastian Sylvan wrote:
2008/5/17 Kaveh Shahbazian
: I have question on mapping some Haskell concepts to C# 3 ones. Maybe there are not any strict equivalents; yet it helps: 1 - What is the equivalent of "Type Constructor" in C#?
Class declaration. Generic ones. E.g. List<int>, is a type where the type constructor List has been applied to the type int.
2 - What is the equivalent of "Data Constructor" in C#?
Constructors, I guess.
3 - What is the logical implementation of pattern matching in C#? (For example using structures with indicator fields or using interfaces and inheritance and dynamically dispatch in calling overloaded methods. Also this question contain a hidden one...GADTs!)
You can use an abstract base class, and then inherit one class for each constructor (e.g. base class Expression, and concrete subclasses Mul, Add, etc.). Then you can use runtime type reflection to figure out which kind of Expression you have and branch on it.
Ideally you would use dynamic dispatch, not "type reflection" for this, e.g. abstract class List<A> { public abstract int Length(); public abstract List<A> Append(List<A> xs); public abstract B Foldr<B>(Func cons, B nil); } class Nil<A> : List<A> { public Nil() {} public override int Length() { return 0; } public override List<A> Append(List<A> xs) { return xs; } public override B Foldr<B>(Func cons, B nil) { return nil; } } class Cons<A> : List<A> { public Cons(A a, List<A> as) { Head = a; Tail = as; } public override int Length() { return 1 + Tail.Length(); } public override List<A> Append(List<A> xs) { return new Cons<A>(Head, Tail.Append(xs)); } public override B Foldr<B>(Func cons, B nil) { return cons(Head,Tail.Foldr(cons,nil)); } public readonly A Head; public readonly List<A> Tail; } The Foldr method does make some constructors a bit special, but not too much. class Append<A> : List<A> { public Append(List <A> xs, List<A> ys) { Front = xs; Back = ys; } public override int Length() { return Front.Length() + Back.Length(); } public override List<A> Append(List<A> ys) { return new Append<A>(this, ys); } public override B Foldr<B>(Func cons, B nil) { Front.Foldr(cons, Back.Foldr(cons, nil)); } public readonly List<A> Front, Back; } We could, of course, define Cons.Append to use the Append class instead.

Hi (I did not received your message in my mail box and I have seen it on mailing list. I dot know why this happened (?).) /* Maybe I am misguessing why you are asking your question, but wouldn't it be better to ask how to map these Haskell concepts to CLR? If so, check out work on Mondrian. */ My intention is to employ Haskell techniques in C# where it fits. If I were going to implement Haskell on CLR the way you mentioned was proper. For something like: type Thing a b = ThisWay a | ThatWay b | NoWay actually there is no equivalents for data constructor in C# 3 (I think). I asked it if there are other ideas about this: Controlling the execution path by deciding based of structure of data with a trick other than reflecting! Thank you

On 2008 May 18, at 9:59, Kaveh Shahbazian wrote:
For something like: type Thing a b = ThisWay a | ThatWay b | NoWay actually there is no equivalents for data constructor
I presume you mean "data" instead of "type". Not that I can address your question directly, as I don't know C#. In C it's a union; in C++ you would export constructors ThisWay(), ThatWay(), NoWay() from class Thing. I presume C# is similar. Haskell syntax is decidedly more compact than any of them.
in C# 3 (I think). I asked it if there are other ideas about this: Controlling the execution path by deciding based of structure of data with a trick other than reflecting!
in C-like languages, the class includes a structure tag which is set by the constructor. Guess what? That's how Haskell does it, just implicitly (hence, again, nicely compact syntax). (You can actually experiment with this in GHC; using internal stuff like UnsafeCoerce# you can coerce one datum to another if they have the same (0-based, assigned in order of definition) constructor tag and the same representation for the data value. IIRC in GHC the internal constructor tag is an 8-bit unsigned value.) To make the above a bit clearer (I hope), here's a rough C approximation of a simple Haskell type: /* data Foo = FooInt Int | FooDouble Double */ struct Foo { unsigned char _FooTag; union { #define _FooTag_FooInt 0 int _FooInt; #define _FooTag_FooDouble 1 double _FooDouble; } _Foo_u; }; /* here I assume unboxed basic types for simplicity */ struct Foo *FooInt(int param) { Foo *foo = malloc(sizeof *foo); /* assume sane error checking here */ foo->_FooTag = _FooTag_FooInt; foo->_Foo_u._FooInt = param; } struct Foo *FooDouble(int param) { Foo *foo = malloc(sizeof *foo); /* assume sane error checking here */ foo->_FooTag = _FooTag_FooDouble; foo->_Foo_u._FooDouble = param; } /* * bar (FooInt i) = ... * desugars to * bar x = case x of { FooInt i -> ... } * which is very roughly (pretend I catch x == 0 and invoke error("Undefined")) * bar(Foo x) { switch (x->_FooTag) { case _FooTag_FooInt: i = x->_Foo_u._FooInt; ... } } */ -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

2008/5/17 Kaveh Shahbazian
3 - What is the logical implementation of pattern matching in C#? (For example using structures with indicator fields or using interfaces and inheritance and dynamically dispatch in calling overloaded methods. Also this question contain a hidden one...GADTs!)
C# is missing ADT's, so the most straightforward way to do it is using open derived classes. (Forgive if my syntax is a bit wrong, you get the idea) class Thing { } class ThisWay : Thing { public a value; } class ThatWay : Thing { public b value; } class NoWay : Thing { } Annoyances include having to parameterize the, ahem, "constructors" on all type parameters, and the openness of the cases. That is, there is nothing stopping someone from adding "class TwoWay" later and making your pattern-matches partial. Scala is very much like C#, but gets this point right, FWIW. A more subtle trick is to use the fold of the ADT as its representation. delegate c Thing(Func thisWay, Func thatWay, c noWay) Then your constructors look like this (if I remember C#'s lambda syntax correctly): ThisWay thisWay(a value) { return new ThisWay((thisC, thatC, noC) => thisC(value)); } ... And a pattern match looks like this: String desc = thing( x => "ThisWay " + x.toString(), x => "ThatWay " + x.toString(), () => "NoWay"); Which isn't all that bad, actually. An advantage is that this approach does in fact keep the data type closed: you can be sure that the thing() pattern match does in fact cover all cases of the data type. A disadvantage is that there is rather a lot of plumbing (not really in comparison to the open derived approach though, I suppose). After those C# guys went to all the trouble to add lambdas and half-assed type-inference (not that "full-assed" was possible in their type system, but there are more complete strategies than the one they took), they could have at least added some half-assed (read: non-G) ADTs for us too :-). Luke

On Sunday 18 May 2008 16:33:56 Luke Palmer wrote:
Scala is very much like C#, but gets this point right, FWIW.
Only for certain types, IIRC. Scala was broken with respect to bools the last time I looked. -- Dr Jon D Harrop, Flying Frog Consultancy Ltd. http://www.ffconsultancy.com/products/?e
participants (6)
-
Brandon S. Allbery KF8NH
-
Derek Elkins
-
Jon Harrop
-
Kaveh Shahbazian
-
Luke Palmer
-
Sebastian Sylvan