Representing Hierarchies with Typeclasses

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Representing Hierarchies with Typeclasses

Rahul Muttineni
Hi cafe,

I want to embed Java class hierarchies in Haskell, but I am unable to find a clean way to do it.

Assume the class hierarchy C derives from B derives from A.

Partial Solution:
---
type family Super (a :: *) :: *

class Extends a b where
  supercast :: a -> b

instance {-# INCOHERENT #-} (Class a, Class c, Super a ~ b, Super b ~ c) => Extends a c where

data A
data B
data C

type instance Super C = B
type instance Super B = A
instance Extends C B
instance Extends B A
--

This is fine and is successfully able to infer Extends C A, but it's redundant and cannot infer that Extends D A if we let Super D = C. Is there a way to only specify the parent-child relationship once and get GHC to infer the entire hierarchy without the use of UndecidableInstances?  Other solutions I've tried which avoid redundancy cause an infinite loop in the context reduction step of GHC.

Thanks,
Rahul Muttineni

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Representing Hierarchies with Typeclasses

Rahul Muttineni
Taking inspiration from http://stackoverflow.com/questions/24775080/how-to-establish-an-ordering-between-types-in-haskell, this comes out to be the solution:
---
type family Super (a :: *) :: *

class Extends a b where
  supercast :: a -> b

instances Extends a a
instance {-# INCOHERENT #-} (Super a ~ b, Extends b c) => Extends a c
---
But this solution does rely on UndecidableInstances, but since it works it's fine.


On Wed, Oct 5, 2016 at 10:01 AM, Rahul Muttineni <[hidden email]> wrote:
Hi cafe,

I want to embed Java class hierarchies in Haskell, but I am unable to find a clean way to do it.

Assume the class hierarchy C derives from B derives from A.

Partial Solution:
---
type family Super (a :: *) :: *

class Extends a b where
  supercast :: a -> b

instance {-# INCOHERENT #-} (Class a, Class c, Super a ~ b, Super b ~ c) => Extends a c where

data A
data B
data C

type instance Super C = B
type instance Super B = A
instance Extends C B
instance Extends B A
--

This is fine and is successfully able to infer Extends C A, but it's redundant and cannot infer that Extends D A if we let Super D = C. Is there a way to only specify the parent-child relationship once and get GHC to infer the entire hierarchy without the use of UndecidableInstances?  Other solutions I've tried which avoid redundancy cause an infinite loop in the context reduction step of GHC.

Thanks,
Rahul Muttineni



--
Rahul Muttineni

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Representing Hierarchies with Typeclasses

Dimitri DeFigueiredo
In reply to this post by Rahul Muttineni
I have looked at how to embedded object oriented systems into haskell
for practical reasons.
By far the best resource I found was Oleg Kiselyov and Ralph Lämmel's work:

https://arxiv.org/pdf/cs/0509027.pdf

It shows the multiple possibilities.
I have used the idea of having a super class be a polymorphic type with
a tail.

data Point s = Pt { x :: Int, y:: Int, tail :: s}

And then specializing the parameter s into your derived class

type Radius = Int
type Circle = Point Radius

many times.

But *be warned*, I try to avoid object hierarchies like the plague! They
lead to code that is not reusable.
You may want to consider other simpler possibilities. Here is one of my
earlier experiments that may be useful to you (I no longer have the
views expressed there).

https://github.com/dimitri-xyz/inheritance-in-haskell

Cheers,

Dimitri

--
2E45 D376 A744 C671 5100 A261 210B 8461 0FB0 CA1F


_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Representing Hierarchies with Typeclasses

Bardur Arantsson-2
In reply to this post by Rahul Muttineni
On 2016-10-05 06:31, Rahul Muttineni wrote:
> Hi cafe,
>
> I want to embed Java class hierarchies in Haskell, but I am unable to
> find a clean way to do it.
>

Is this purely an academic exercise, or are you trying to solve some
higher-level ("real") problem?

If it's the latter then it might be a better idea to describe the
overall problem you're trying to solve. (I.e. this may be an instance of
the "XY Problem".)

Regards,

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Representing Hierarchies with Typeclasses

Rahul Muttineni
Hi Bardur,

The hierarchy will be used for FFI in GHCVM - my effort at bringing the Haskell to the JVM. My goal has been to make FFI Haskell code look pretty close to Java code and thereby not making it intimidating for newcomers coming from Java, while demonstrating that monads are powerful enough to embed a Java-like language inside of Haskell without using types that would be confusing to a newcomer - like the ST monad and its use of rank-2 types.

Currently, if you want to store raw Java objects inside of Haskell in GHCVM, you do:

```haskell
data {-# CLASS "java.lang.String" #-} JString = JString (Object# JString)
```

Note that Object# (c :: *) :: # is a new primitive type constructor I introduced to allow raw Java objects to be stored in data types. It's only type-safe to do this if the underlying object is immutable or locally immutable (doesn't change much during the time of use).

This above type definition, while confusing, is succinct and kills two birds with one stone:
1) It allows JString to be used as a 'tag type' that stores metadata on the class of the underlying object it stores.
2) It allows JString to be used as a boxed representation of a raw Java object, just as Int is a boxed version of Int#.

There's also the Java monad:

```haskell
newtype Java c a  = Java (Object# c -> (# Object# c, a #))
```

The c is the tag type - essentially it determines the underlying representation of the threaded 'this' pointer. This is a special monad recognized by GHCVM.

The final goal is to be able to import methods from java without doing manual casting at the Haskell level - it uses the Extends typeclass to handle that for you.

For example, assume you need to import the java.lang.Object.toString() method from Java. Obviously, you wouldn't want to re-import this method for every possible Java class you ever interact with. Instead, you would import it like so:

```haskell
data {-# CLASS "java.lang.Object" #-} Object = Object (Object# Object)

type instance Super JString = Object

foreign import java unsafe "toString" toJString :: Extends a Object => Java a JString

getStringFromString :: Java JString JString
getStringFromString = toJString

getStringFromObject :: Java Object JString
getStringFromObject = toJString
```

So this allows for reuse of a single foreign import in multiple particular cases as shown above. To see a more "real-world" example of this in action, check out the example JavaFX project that compiles with GHCVM [1].

I'm open to suggestions on better ways to accomplish the same goal.

Thanks,
Rahul


On Wed, Oct 5, 2016 at 7:42 PM, Bardur Arantsson <[hidden email]> wrote:
On 2016-10-05 06:31, Rahul Muttineni wrote:
> Hi cafe,
>
> I want to embed Java class hierarchies in Haskell, but I am unable to
> find a clean way to do it.
>

Is this purely an academic exercise, or are you trying to solve some
higher-level ("real") problem?

If it's the latter then it might be a better idea to describe the
overall problem you're trying to solve. (I.e. this may be an instance of
the "XY Problem".)

Regards,

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.



--
Rahul Muttineni

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Representing Hierarchies with Typeclasses

Rahul Muttineni
In reply to this post by Dimitri DeFigueiredo
Hi Dimitri, 

Thanks for the link! I'll take a look. The goal of doing this was to make foreign Java imports reusable for subclasses in GHCVM.

Thanks,
Rahul

On Wed, Oct 5, 2016 at 7:25 PM, Dimitri DeFigueiredo <[hidden email]> wrote:
I have looked at how to embedded object oriented systems into haskell
for practical reasons.
By far the best resource I found was Oleg Kiselyov and Ralph Lämmel's work:

https://arxiv.org/pdf/cs/0509027.pdf

It shows the multiple possibilities.
I have used the idea of having a super class be a polymorphic type with
a tail.

data Point s = Pt { x :: Int, y:: Int, tail :: s}

And then specializing the parameter s into your derived class

type Radius = Int
type Circle = Point Radius

many times.

But *be warned*, I try to avoid object hierarchies like the plague! They
lead to code that is not reusable.
You may want to consider other simpler possibilities. Here is one of my
earlier experiments that may be useful to you (I no longer have the
views expressed there).

https://github.com/dimitri-xyz/inheritance-in-haskell

Cheers,

Dimitri

--
2E45 D376 A744 C671 5100 A261 210B 8461 0FB0 CA1F





--
Rahul Muttineni

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.