shared interface Smth<in Klass> given Klass satisfies Class<>{
shared formal void smth(Klass klass);
}
shared object smth satisfies Smth<Class<String>>{
shared actual void smth(Class<String,Nothing> klass) {}
}
`SmthImpl` :
shared class SmthImpl() satisfies Smth<Class<String>>{
shared actual void smth(Class<String,Nothing> klass) {}
}
I get an error:type with contravariant type parameter 'Class' appears in contravariant or invariant location in supertype: 'Smth<Class<String,Nothing>>'
shared class SmthImpl() satisfies Smth<Class<String>>
Furthermore, a type with a contravariant type parameter may only appear in a covariant position in an extended type, satisfied type, case type, or upper bound type constraint.
Note: this restriction exists to eliminate certain undecidable cases described in the paper Taming Wildcards in Java's Type System, by Tate et al.
--
You received this message because you are subscribed to the Google Groups "ceylon-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ceylon-users...@googlegroups.com.
To post to this group, send email to ceylon...@googlegroups.com.
Visit this group at https://groups.google.com/group/ceylon-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/ceylon-users/4e52dcb7-2638-4d18-8ee5-6e6e25388b43%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
shared serializable class Model{
shared String id;
shared Boolean isSomething;
shared Integer someNumber;
}
shared serializable class Other{
shared Integer id;
shared String isSomething;
shared Float someNumber;
}
Model modelInstance = Model("123",false,123);
assert(is Other other=api.convert(modelInstance,`Other`));
shared interface TypedConverter<in Source=Nothing ,in ResultType=Nothing,out Result=Anything> satisfies Component given ResultType satisfies Type<Result> {
throws(`class ConvertionException`)
shared formal Result convert(Context context,Source source,ResultType resultType);
shared interface Matcher {
shared formal Boolean match(Source source,ResultType resultType);
}
shared default Matcher? matcher=>null;
}
shared class MetaConverter() satisfies TypedConverter<Object,ClassOrInterface<Object>,Object> {
shared actual Object convert(Context context, Object source, ClassOrInterface<Object> resultType) {
value resolvedType = context.resolve(resultType);
value description = context.describe(source, resolvedType);
value accumulator =context.create(description.accumulatorClass, null);
for(value part in description.parts){
value sourcePart = part.obtainable.obtain;
value destPart=context.convert(sourcePart, part.targetable.type);
if(exists error=accumulator.accumulate(part.targetable, destPart)){
throw ConvertionException(source, resultType,error);
}
}
return context.create(resolvedType, accumulator);
}
matcher => object satisfies MetaConverter.Matcher{
shared actual Boolean match(Object source, ClassOrInterface<Object> resultType) =>true;
};
}
shared interface TypedResolver<out Base=Anything,out Output=Anything, in Input=Nothing> satisfies Component given Input satisfies Type<Base> {
shared formal Class<Output> resolve(Input type);
shared interface Matcher {
shared formal Boolean match(Input inputType);
}
shared formal Matcher? matcher;
}
shared class SelfResolver() satisfies TypedResolver<Anything,Anything,ClassOrInterface<Anything>>{
shared actual Class<Anything,Nothing> resolve(ClassOrInterface<Anything> type){
assert(is Class<Anything> type);
return type;
}
matcher=> object satisfies SelfResolver.Matcher{
shared actual Boolean match(ClassOrInterface<Anything> inputType) => inputType is Class<Anything>;
};
}
On Jul 30, 2018, at 5:31 AM, Voitech <wojciech...@gmail.com> wrote:
Thanks John for Your answer, so the error is according to docs. I still need to constrain method parameter with Type<>, to be able to distinct: is It ClassOrInterface? Maybe Interface or Class or ClassModel ? Or Union? It is vital for my lib's API or it will not be type safe. So the use case...I work on library for converting one type to another, with runtime selection on how to do that. So let say You have few model.
shared serializable class Model{
shared String id;
shared Boolean isSomething;
shared Integer someNumber;
}
Another one
shared serializable class Other{
shared Integer id;
shared String isSomething;
shared Float someNumber;
}
Let's create an object
Model modelInstance = Model("123",false,123);We can call
assert(is Other other=api.convert(modelInstance,`Other`));And it already worksTo achive this You need a Converter which will do the convertion for You.Declaration:
shared interface TypedConverter<in Source=Nothing ,in ResultType=Nothing,outResult=Anything> satisfies Component given ResultType satisfies Type<Result> {
throws(`class ConvertionException`)
shared formal Result convert(Context context,Source source,ResultTyperesultType);
shared interface Matcher {
shared formal Boolean match(Source source,ResultType resultType);
}
shared default Matcher? matcher=>null;
}
An implementation:
shared class MetaConverter() satisfies TypedConverter<Object,ClassOrInterface<Object>,Object> {
shared actual Object convert(Context context, Object source,ClassOrInterface<Object> resultType) {
value resolvedType = context.resolve(resultType);
value description = context.describe(source, resolvedType);
value accumulator =context.create(description.accumulatorClass, null);
for(value part in description.parts){
value sourcePart = part.obtainable.obtain;
value destPart=context.convert(sourcePart, part.targetable.type);
if(exists error=accumulator.accumulate(part.targetable, destPart)){
throw ConvertionException(source, resultType,error);
}
}
return context.create(resolvedType, accumulator);
}
matcher => object satisfies MetaConverter.Matcher{
shared actual Boolean match(Object source, ClassOrInterface<Object>resultType) =>true;
};
}
As can be seen I use Context calls to delegate some responsibilities. There are other support components for generic convertion, like Resolver, which provides specific Class<Kind> for abstract classes, interfaces or intersection types. One of such is SelfResolver it is used, when other components requests resolvance, of unknown (mostly Type<Anything>) to some specific Class<Other>. It may be so, that this provided type is already a Class<Other> but it is not the job to check that by calling component (in this case MetaConverter) but it does delegated to Resolver to ensure that. It's parent's type definition looks like this:
shared interface TypedResolver<out Base=Anything,out Output=Anything, inInput=Nothing> satisfies Component given Input satisfies Type<Base> {
shared formal Class<Output> resolve(Input type);
shared interface Matcher {
shared formal Boolean match(Input inputType);
}
shared formal Matcher? matcher;
}
implementation looks like this:
shared class SelfResolver() satisfies TypedResolver<Anything,Anything,ClassOrInterface<Anything>>{
shared actual Class<Anything,Nothing> resolve(ClassOrInterface<Anything>type){
assert(is Class<Anything> type);
return type;
}
matcher=> object satisfies SelfResolver.Matcher{
shared actual Boolean match(ClassOrInterface<Anything> inputType) =>inputType is Class<Anything>;
};
}
Because I need to store components somehow, I need to be able to type something like TypedResolver<>,so none of 3 type parameters, can be declared as invariant, as invariant type parameters don't have super types like Nothing/Anything, when in runtime there will be request to resolve type from other component (MetaConveter in this case), which is already a Class<>. I use Matcher for that (Iteration over registered Resolvers and calling match on every of them, not very optimal but this is not the case). The third type parameter in TypedResolver<Anything,Anything,ClassOrInterface<Anything>>, (in Input=Nothing), declaration is telling that method parameter inputType in resolve and matchmust be bound by this type parameter. As You can see I do assert in resolve method, and a check in match method. It is type safety flaw. I shouldn't be forced by type system to do so, but I can't constrain third parameter of TypeResolver with Class<>, as it gives me this error "Type with contravariant type parameter Class appears in contravariant or invariant location in supertype: TypedResolver<Anything,Anything,Class<Anything,Nothing>>".
To view this discussion on the web visit https://groups.google.com/d/msgid/ceylon-users/751e165b-bfc4-4685-9b3f-8879983bcd63%40googlegroups.com.
Thank You, John for all Your help. I will take a look on this holder workaround.
--
You received this message because you are subscribed to the Google Groups "ceylon-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ceylon-users+unsubscribe@googlegroups.com.
To post to this group, send email to ceylon...@googlegroups.com.
Visit this group at https://groups.google.com/group/ceylon-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/ceylon-users/34573f9a-adac-4704-bf89-d0bb704df1f9%40googlegroups.com.