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