Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problems with Function being returned? #323

Closed
s4ke opened this issue Jan 16, 2017 · 5 comments
Closed

Problems with Function being returned? #323

s4ke opened this issue Jan 16, 2017 · 5 comments
Assignees
Labels

Comments

@s4ke
Copy link

s4ke commented Jan 16, 2017

I want to implement the following:

class Arrow a => ArrowApply a where
    app :: a (a b c, b) c

instance ArrowApply (->) where
    app (f, b) = f b

but I get this error during the Java compilation step:

error: incompatible types: U<TTuple2<U<?,?>,?>,?> cannot be converted to B<U<?,?>,TTuple
2<B<U<?,?>,?,?>,?>,?>
        >app().call();
                   ^
  where ?,? are type-variables:
    ? extends Object declared in method <?,?>âapp()
    ? extends Object declared in method <?,?>âapp()
1 error

This is due to this code being wrongly generated:

final public static class IArrowApply_$minus$gt implements CArrowApply<Func.U<?, ?>> {
  public IArrowApply_$minus$gt() {}
  final public static IArrowApply_$minus$gt it = new IArrowApply_$minus$gt();
  @Override final public <𝓒, 𝓑> Kind.B<Func.U<?, ?>, PreludeBase.TTuple2<Kind.B<Func.U<?, ?>, 𝓑, 𝓒>, 𝓑>, 𝓒> ƒapp() {
    return (Kind.B<Func.U<?, ?>, PreludeBase.TTuple2<Kind.B<Func.U<?, ?>, 𝓑, 𝓒>, 𝓑>, 𝓒>)IArrowApply_$minus$gt.<
          𝓒, 𝓑
        >app().call();
  }
//...
  final public static <α, β> Lazy<Func.U<PreludeBase.TTuple2<Func.U<β, α>, β>, α>> app() {
    return (Func.U<PreludeBase.TTuple2<Func.U<β, α>, β>, α>)((final Lazy<PreludeBase.TTuple2<Func.U<β, α>, β>> arg$8203) -> {
              final PreludeBase.TTuple2<Func.U<β, α>, β> $8204 = arg$8203.call();
              final Func.U<β, α> f$7728 = $8204.mem1.call();
              return Thunk.<α>nested((Lazy<Lazy<α>>)(() -> f$7728.apply($8204.mem2)));
            });
  }
}

However, if I remove the .call() from ƒapp() this would compile (accordingly to IntelliJ code highlighting).

final public static class IArrowApply_$minus$gt implements CArrowApply<Func.U<?, ?>> {
  public IArrowApply_$minus$gt() {}
  final public static IArrowApply_$minus$gt it = new IArrowApply_$minus$gt();
  @Override final public <𝓒, 𝓑> Kind.B<Func.U<?, ?>, PreludeBase.TTuple2<Kind.B<Func.U<?, ?>, 𝓑, 𝓒>, 𝓑>, 𝓒> ƒapp() {
    return (Kind.B<Func.U<?, ?>, PreludeBase.TTuple2<Kind.B<Func.U<?, ?>, 𝓑, 𝓒>, 𝓑>, 𝓒>)IArrowApply_$minus$gt.<
          𝓒, 𝓑
        >app();
  }
//...
  final public static <α, β> Lazy<Func.U<PreludeBase.TTuple2<Func.U<β, α>, β>, α>> app() {
    return (Func.U<PreludeBase.TTuple2<Func.U<β, α>, β>, α>)((final Lazy<PreludeBase.TTuple2<Func.U<β, α>, β>> arg$8203) -> {
              final PreludeBase.TTuple2<Func.U<β, α>, β> $8204 = arg$8203.call();
              final Func.U<β, α> f$7728 = $8204.mem1.call();
              return Thunk.<α>nested((Lazy<Lazy<α>>)(() -> f$7728.apply($8204.mem2)));
            });
  }
}

I have read somewhere that this can be due to the fact that Frege doesn't have support for Functions being returned as objects. But is this really due to that as the fix is would be quite easy?

Am I missing something? If no, can I somehow work around this (maybe by declaring native Java code?

@s4ke s4ke changed the title Problems with Function being returned Problems with Function being returned? Jan 16, 2017
@Ingo60 Ingo60 self-assigned this Jan 17, 2017
@Ingo60 Ingo60 added the bug label Jan 17, 2017
@Ingo60
Copy link
Member

Ingo60 commented Jan 17, 2017

This is most probably a compiler error.
Let me analyze it and try to fix it or find a workaround.

BTW, great documentation.

@s4ke
Copy link
Author

s4ke commented Jan 17, 2017

Oh, and I am using frege 3.24.100.1-jdk8

This is most probably a compiler error.
Let me analyze it and try to fix it or find a workaround.

Awesome. Thanks!

BTW, great documentation.

Always. How else would you be able to help me :)?

@Ingo60
Copy link
Member

Ingo60 commented Jan 17, 2017

The error comes about because of difficulities with the encoding of higher kinds in Java. Since type variables in Java can only have kind * we use an encoding like

Kind.B<A.B,C>

for Haskell

a b c

This worked fine so far in type classes, but in your case the we have the more complex

a (a b c, b) c

where the second a appears as type argument of the tuple which itself appears as the type argument of the function. Therefore, the cast fails in the instance for (->). Although Java knows that an unary function
Func.U<B,C> is by definition a Kind.B<Func.U<?,?>, B, C> (i.e. the former extends the latter), it does not know that the types are in fact identical by design (this one cannot express in Java). Hence it refuses to cast the type arguments also.

This happens apparently only with type classes/instances where the implementation uses subtyping. Interestingly, the following encoding of the type class works fine:

-- "type class"
data ArrowApply a b c = AA { app :: a (a b c, b) c }

-- "instance" for (->)
aafunc = AA { app = xapp}
    where xapp (f, b) = f b

-- use it
main = println (aafunc.app ((1+), 3))

I'll check if I can repair the code generation for instances with higher kinded type arguments. But it may take until next week.

@s4ke
Copy link
Author

s4ke commented Jan 17, 2017

Ah thanks, I think this will suit me more however:

data ArrowApply' a b c = AA { app :: a (a b c, b) c }

aafunc = AA { app = xapp}
    where xapp (f, b) = f b
    
class Arrow a => ArrowApply a where
    app :: ArrowApply' a b c
    
instance ArrowApply (->) where
    app = aafunc

@s4ke
Copy link
Author

s4ke commented Jan 17, 2017

Or even better (this gives me the exact same syntax):

data ArrowApply' a b c = AA { app :: a (a b c, b) c }

-- "instance" for (->)
aafunc = AA { app = xapp}
    where xapp (f, b) = f b
    
class Arrow a => ArrowApply a where
    app' :: ArrowApply' a b c
    
instance ArrowApply (->) where
    app' = aafunc
    
app :: ArrowApply a => a (a b c, b) c
app = app'.app

Thanks a lot :)

@Ingo60 Ingo60 closed this as completed in cb024ef Jan 30, 2018
Ingo60 added a commit that referenced this issue Jan 30, 2018
catull pushed a commit to catull/frege that referenced this issue Jun 28, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants