Representing Hierarchies with Typeclasses

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

Taking inspiration from
http://stackoverflow.com/questions/24775080/how-to-establish-an-ordering-bet...,
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
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

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,

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
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
participants (2)
-
Bardur Arantsson
-
Rahul Muttineni