Subtype polymorphism in Haskell
Hi, I am porting a C++ program to Haskell. My current task is to take a class hierarchy and produce something equivalent in Haskell, but I don't seem to be able to get a grip on how type classes and instances contribute to the solution. Can anyone enlighten me? Roughly, the class hierarchy in C++ is of the form class A { public: virtual int do_x(int,int) = 0; }; class B { public: int do_x(int x,int y) { ...} }; class C { public: int do_x(int x,int y) { ...} }; Any help would be greatly appreciated. Thanks Simon courtenage@gmail.com
My guess is that it's class B : public A and class C : public A In this case it seems perfect to use type classes: class A t where do_x :: t -> Integer -> Integer -> Integer data B = ... instance A B where do_x b x y = ... data C = ... instance A C where do_x c x y = ... If you want some general "A" object, you can use existentials (or, better yet, GADTs): data A_general = forall t. A t => A_general t or data A_GADT where A_GADT :: A t => t -> A_GADT so that int foo (A v) {... v.do_x(1,2)...} becomes foo :: A_GADT -> Integer foo (A_GADT v) = ... do_x v 1 2 ... Simon Courtenage wrote:
Hi,
I am porting a C++ program to Haskell. My current task is to take a class hierarchy and produce something equivalent in Haskell, but I don't seem to be able to get a grip on how type classes and instances contribute to the solution. Can anyone enlighten me?
Roughly, the class hierarchy in C++ is of the form
class A { public: virtual int do_x(int,int) = 0; };
class B { public: int do_x(int x,int y) { ...} };
class C { public: int do_x(int x,int y) { ...} };
Any help would be greatly appreciated.
Thanks
Simon courtenage@gmail.com <mailto:courtenage@gmail.com>
------------------------------------------------------------------------
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
My thanks to everyone who replied with their helpful comments. You are right that I forgot to add the public inheritance on the C++ classes (that's what happens when you write code in an email without passing it through a compiler first). I like the idea below, which is easy to understand. It seems to me, though, that there's a lot more to the use of typeclasses than is covered in some of the haskell textbooks, and if anyone knows of a good in-depth treatment of this, I would be grateful for a pointer. Thanks again to everyone who responded, Simon On Mon, Jul 5, 2010 at 2:28 PM, Miguel Mitrofanov <miguelimo38@yandex.ru>wrote:
My guess is that it's class B : public A and class C : public A
In this case it seems perfect to use type classes:
class A t where do_x :: t -> Integer -> Integer -> Integer data B = ... instance A B where do_x b x y = ... data C = ... instance A C where do_x c x y = ...
If you want some general "A" object, you can use existentials (or, better yet, GADTs):
data A_general = forall t. A t => A_general t
or
data A_GADT where A_GADT :: A t => t -> A_GADT
so that
int foo (A v) {... v.do_x(1,2)...}
becomes
foo :: A_GADT -> Integer foo (A_GADT v) = ... do_x v 1 2 ...
Simon Courtenage wrote:
Hi,
I am porting a C++ program to Haskell. My current task is to take a class hierarchy and produce something equivalent in Haskell, but I don't seem to be able to get a grip on how type classes and instances contribute to the solution. Can anyone enlighten me?
Roughly, the class hierarchy in C++ is of the form
class A { public: virtual int do_x(int,int) = 0; };
class B { public: int do_x(int x,int y) { ...} };
class C { public: int do_x(int x,int y) { ...} };
Any help would be greatly appreciated.
Thanks
Simon courtenage@gmail.com <mailto:courtenage@gmail.com>
------------------------------------------------------------------------
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- ------------------------------------------------------------------------ Simon Courtenage | simoncourtenage.wordpress.com Twitter: simoncourtenage | Skype: simon99ctg Facebook: Simon Courtenage | IM: simon2263@hotmail.com
Actually, I liked Tillmann Rendel's idea much better than my own one: data A = A {do_x :: Int -> Int -> Int} b = A {do_x = \x y -> ...} c = A {do_x = \x y -> ...} Simon Courtenage wrote:
My thanks to everyone who replied with their helpful comments. You are right that I forgot to add the public inheritance on the C++ classes (that's what happens when you write code in an email without passing it through a compiler first).
I like the idea below, which is easy to understand. It seems to me, though, that there's a lot more to the use of typeclasses than is covered in some of the haskell textbooks, and if anyone knows of a good in-depth treatment of this, I would be grateful for a pointer.
Thanks again to everyone who responded,
Simon
On Mon, Jul 5, 2010 at 2:28 PM, Miguel Mitrofanov <miguelimo38@yandex.ru <mailto:miguelimo38@yandex.ru>> wrote:
My guess is that it's class B : public A and class C : public A
In this case it seems perfect to use type classes:
class A t where do_x :: t -> Integer -> Integer -> Integer data B = ... instance A B where do_x b x y = ... data C = ... instance A C where do_x c x y = ...
If you want some general "A" object, you can use existentials (or, better yet, GADTs):
data A_general = forall t. A t => A_general t
or
data A_GADT where A_GADT :: A t => t -> A_GADT
so that
int foo (A v) {... v.do_x(1,2)...}
becomes
foo :: A_GADT -> Integer foo (A_GADT v) = ... do_x v 1 2 ...
Simon Courtenage wrote:
Hi,
I am porting a C++ program to Haskell. My current task is to take a class hierarchy and produce something equivalent in Haskell, but I don't seem to be able to get a grip on how type classes and instances contribute to the solution. Can anyone enlighten me?
Roughly, the class hierarchy in C++ is of the form
class A { public: virtual int do_x(int,int) = 0; };
class B { public: int do_x(int x,int y) { ...} };
class C { public: int do_x(int x,int y) { ...} };
Any help would be greatly appreciated.
Thanks
Simon courtenage@gmail.com <mailto:courtenage@gmail.com> <mailto:courtenage@gmail.com <mailto:courtenage@gmail.com>>
------------------------------------------------------------------------
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org <mailto:Haskell-Cafe@haskell.org> http://www.haskell.org/mailman/listinfo/haskell-cafe
-- ------------------------------------------------------------------------ Simon Courtenage | simoncourtenage.wordpress.com <http://simoncourtenage.wordpress.com> Twitter: simoncourtenage | Skype: simon99ctg Facebook: Simon Courtenage | IM: simon2263@hotmail.com <mailto:simon2263@hotmail.com>
On Monday 05 July 2010 15:22:43, Simon Courtenage wrote:
Hi,
I am porting a C++ program to Haskell. My current task is to take a class hierarchy and produce something equivalent in Haskell, but I don't seem to be able to get a grip on how type classes and instances contribute to the solution. Can anyone enlighten me?
Roughly, the class hierarchy in C++ is of the form
class A { public: virtual int do_x(int,int) = 0; };
class B { public: int do_x(int x,int y) { ...} };
class C { public: int do_x(int x,int y) { ...} };
Any help would be greatly appreciated.
If there's not more to it, class A where do_x :: Int -> Int -> Int instance A B where do_x = whatever instance A C where do_x = somethingElse would solve it.
Thanks
Simon courtenage@gmail.com
Does this work for you? data A a = A (Int,Int) data B data C class A_Class a where do_x :: a -> Int instance A_Class (A B) where do_x (A (a,b)) = a + b instance A_Class (A C) where do_x (A (a,b)) = a - b -- > do_x ((A (1,2)) :: A B) -- 3 -- > do_x ((A (1,2)) :: A C) -- -1 -deech On Mon, Jul 5, 2010 at 9:22 AM, Simon Courtenage <courtenage@gmail.com> wrote:
Hi, I am porting a C++ program to Haskell. My current task is to take a class hierarchy and produce something equivalent in Haskell, but I don't seem to be able to get a grip on how type classes and instances contribute to the solution. Can anyone enlighten me? Roughly, the class hierarchy in C++ is of the form class A { public: virtual int do_x(int,int) = 0; }; class B { public: int do_x(int x,int y) { ...} }; class C { public: int do_x(int x,int y) { ...} }; Any help would be greatly appreciated. Thanks Simon courtenage@gmail.com
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Simon Courtenage wrote:
I am porting a C++ program to Haskell. My current task is to take a class hierarchy and produce something equivalent in Haskell, but I don't seem to be able to get a grip on how type classes and instances contribute to the solution.
They probably do not contribute at all.
class A { public: virtual int do_x(int,int) = 0; };
class B { public: int do_x(int x,int y) { ...} };
class C { public: int do_x(int x,int y) { ...} };
I guess B and C are subclasses of A? If you do not need complicated subtyping schemes, you could consider on of the following two options: You could emphasize the structure of the class hierarchy, or you could emphasize the object abstraction. The structure of the class hierarchy could be represented by an algebraic data type data A = B | C with the do_x function implementing by pattern matching on an A value do_x :: A -> Int -> Int -> Int do_x B = ... do_x C = ... If your classes have fields, they could be added as fields to the data constructors B and C. Alternatively, the object abstraction could be represented by encoding objects as records of first-class functions. data A = A { do_x :: Int -> Int -> Int } b = A {do_x = \x y -> ...} c = A {do_x = \x y -> ...} If your classes have fields, they could be added as arguments to constructor functions b and c. Tillmann
Simon Courtenage wrote:
I am porting a C++ program to Haskell. My current task is to take a class hierarchy and produce something equivalent in Haskell
Did you define that task for yourself, or is someone else asking you to do it? There really isn't anything equivalent in Haskell. Typeclasses in Haskell are not the same as classes in C++. You may or may not need typeclasses in your Haskell program (probably not), but whether or not you need them and how you will structure them if you do has little or nothing to do with what the class hierarchy looks like in C++. The only way to do a good job of porting a program from C++ to Haskell is to begin with a description of what the program does and what its requirements are. Regards, Yitz
Simon Courtenage wrote:
This is for a project to port an open-source C++ library to haskell.
Great! We'd love to give you whatever support you need for your efforts.
My initial plan is to more or less preserve the way the library works in the first draft of the port and see how far we can get like that
That's fine, as long as you truly mean the way it works, and not the way the code is structured. Haskell is a post-OO language. Its abstractions are very different than class structures in C++. There is no direct translation - any given C++ class structure could correspond to many totally different kinds of Haskell programs, depending on what the program is trying to do. If you are trying to find a method to transliterate a strongly OO-style C++ program more or less word for word into Haskell in a way that the class structure of the C++ will still be apparent in the result, you are likely in for a frustrating experience. You will spend a lot more time than you expected, and the results will be very unsatisfying. Many others have ended up that way. On the other hand, if you are willing to be a little more flexible in your thinking, you'll probably find the task much easier than you thought, enjoy it, and reap many benefits from the process that you never imagined. In any case, please keep us in the loop, we'd like to hear how it's going. And, uh... would you be willing to share a few more details about what it is that you're trying to port? ;) Thanks, Yitz
participants (7)
-
aditya siram -
Daniel Fischer -
Miguel Mitrofanov -
Simon Courtenage -
Tillmann Rendel -
Yitzchak Gale -
Yves Parès