Open csierra opened 7 years ago
As we discussed via Gists, the best approach is to have JWT-specific typeclasses like JMonad
, JApplicative
, and JFunctor
. Once you've played around with it, and you'll figured out all the functionality you need for your use-cases, we can collect all the definitions into a Java.Do
module and add it to the standard library. Once it's been added, I'll close this issue.
Adding this to the v0.1.0 milestone.
hey @rahulmutt... thanks
so then there would be no other trick/magic to circumvent the (Class a)
constraint?
If I understand it correctly this all happens because of the restriction of wrapping a GHC function into a java Function
using @wrapper
. Wouldn't be any smoother way of implementing a java Function
from a haskell one?
Nope, unless I add special support for it and I don't think that would be a good idea, and here's why:
Take the following code as an example:
data SomeInteger = SomeInteger Int
f :: SomeInteger -> SomeInteger
f (SomeInteger i) = i'
where i' = SomeInteger $ inc i
inc x = x + 1
Does it make sense to translate f
directly to Function SomeInteger SomeInteger
? No, because the function f
is lazy. It returns a thunk. A Function SomeInteger SomeInteger
should be strict in its argument and return type by Java semantics.
Moreover, the Java-level representation of SomeInteger
is not your typical Java object since it is designed to account for laziness. Due to these semantic differences between Java and Eta (particularly due to laziness vs strictness), we only allow you to create a Function
(or any interface) only from datatypes we know will be simple, non-lazy objects.
In this case, the Class
constraint guarantees that for us. JWTs are simple wrappers around Java objects and are strict
in the wrapping (meaning you must have an evaluated Java object inside at all times) and hence we know we can safely pass them between boundary of Eta and Java without mismatch in semantics.
I can imagine that this boundary will cause annoyances at times (we observed this when working with Apache Spark in Eta) but I think we can find ways to make it more convenient without loss of safety with some type system features. This boundary is what allows us to safely interact with the Java world from a purely functional language like Eta.
If you have specific use cases where you want to relax this restriction and the translation toFunction
still makes sense, please share them and we can work out how to accommodate those cases in a more general framework.
It seems I bumped into another issue. When jfmap
or jflatMap
methods return an interface (like CompletionStage
I get the following runtime error:
Exception in thread "main" java.lang.IncompatibleClassChangeError: Found interface com.liferay.functional.validation.Validation, but class was expected
at main.Main$zdLr8D6zdcjbind.enter(Unknown Source)
at main.Main$satzus8JV.enter(Unknown Source)
at eta.runtime.apply.Apply$PAPApply.enter(Apply.java:231)
at eta.runtime.apply.StgPAP.apply(StgPAP.java:229)
at eta.runtime.apply.ApPP.stackEnter(ApPP.java:19)
at eta.runtime.stg.StackFrame.enter(StackFrame.java:43)
at eta.runtime.stg.StackFrame.enter(StackFrame.java:26)
at eta.runtime.stg.StgContext.checkForStackFrames(StgContext.java:79)
at main.Main$zdLr8D0zdcshowsPrec.enter(Unknown Source)
at eta.runtime.apply.StgFun.apply(StgFun.java:291)
at eta.runtime.apply.ApPPP.stackEnter(ApPPP.java:21)
at eta.runtime.stg.StackFrame.enter(StackFrame.java:43)
at eta.runtime.stg.StgContext.checkForStackFrames(StgContext.java:79)
at base.ghc.io.handle.Text$zdwa7.enter(Unknown Source)
at base.ghc.io.handle.Text$hPutStr2.enter(Unknown Source)
at base.system.IO$print1.enter(Unknown Source)
at base.system.IO$print.enter(Unknown Source)
at eta.runtime.apply.Apply$PAPApply.enter(Apply.java:231)
at eta.runtime.apply.StgPAP.apply(StgPAP.java:46)
at eta.runtime.apply.ApV.stackEnter(ApV.java:12)
at eta.runtime.stg.StackFrame.enter(StackFrame.java:43)
at eta.runtime.stg.StackFrame.enter(StackFrame.java:26)
at eta.runtime.stg.StackFrame.enter(StackFrame.java:26)
at eta.runtime.stg.Capability.schedule(Capability.java:260)
at eta.runtime.RtsScheduler.scheduleWaitThread(RtsScheduler.java:57)
at eta.runtime.Rts.evalLazyIO(Rts.java:95)
at eta.runtime.Rts.hsMain(Rts.java:38)
at eta.main.main(Unknown Source)
as @Jyothsnasrinivas pointed out, I failed to add "@interface" to the method declaration. Doing so solves the problem.
@csierra I've been reconsidering this and I think it's safe to store Eta types inside of Java generic containers (like Optional
), given the conversation here: https://github.com/typelead/eta/issues/690
Some Java classes present
Functor
orMonad
shapes (likejava.util.Optional
). It would be great to provide instances forFunctor
orMonad
for this types that leverage their native implementations.For example:
currently this is not possible due to the type constraint
(Class a, Class b)
which makesfmap
implementation less polymorphic than the one expected byFunctor