[Haskell-cafe] Representing Hierarchies with Typeclasses

Rahul Muttineni rahulmutt at gmail.com
Wed Oct 5 16:05:20 UTC 2016


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

[1] https://github.com/rahulmutt/ghcvm-javafx

On Wed, Oct 5, 2016 at 7:42 PM, Bardur Arantsson <spam at scientician.net>
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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20161005/0d871f98/attachment.html>


More information about the Haskell-Cafe mailing list