Closed clinuxrulz closed 8 years ago
Interesting! there still cheating going on due to https://github.com/derive4j/hkt/pull/19/files#diff-349805cc9967ae028b3de262d9ccbac0R193
some related post (and comments) I found on the subject:
I think, if we add lower
, we can just typecast refl()
.
Before that we will need to be sure that type constructor in java are injective, but this is probably the case (it is in haskell).
On the other hand, I don't know of any compelling use cases for lower
... do you know one?
type constructor in java are injective
Which means ? (pardon my ignorance)
Type constructors being injective means that for every type constructor F
, F a
equals F b
imply a
equals b
. (ie. the definition of lower
).
Type constructors being injective means that for every type constructor F, F a equals F b imply a equals b. (ie. the definition of lower).
Thanks ! Is 'injective' a cs concept or a mathematical one (such as the bijection that we learn at school) ?
Yes I think that this is the same concept. If you think of F
as a mathematical function, F a
is the image of a
and F b
is the image of b
. Since F
is injective we can track each distinct value of the co-domain (F a
) to a unique and distinct value of the domain (a
) and so if two values of the co-domain are equals it means that their inverse images are equals.
As for safety of lower
:
with our encoding, type constructor witnesses are tied to a particular class: we cannot safely narrow
a hkt term to a subclass of the subclass that implement the __
interface.
I think we should also forbid (mutually) recursive type variables as it can result in unsafe code that type checks.
If we do that, I think, we can assume the same "injectivity law" for type constructors that is valid for ML/Haskell.
Thanks for the explanations. Need to process them for a while...
Forgive me for trying to push again. I'm just trying to prove to myself that it is not type safe.
I've avoided the typecast from Lower_
to Lower
. But maybe something else not allowed is going on. (Note that A and B are simply helpers to get X and Y the right type in the latest example)
I have a hunch that lift
and lower
can aid with implementing type families though the use of type constructors and existential type parameters. (as a use case)
And an implementation of type families leads to a correct implementation of syntactic
from hackage (open unions) https://hackage.haskell.org/package/syntactic
Which leads to DSLs that are extendable.
Edit: Inside syntactic you can find the following code:
-- | The result type of a symbol with the given signature
type family DenResult sig
type instance DenResult (Full a) = a
type instance DenResult (a :-> sig) = DenResult sig
To go from Full a
to a
I believe I need lower
. (And same goes for a :-> sig
)
OK. I believe I've proven type constructors in java are injective. I'm now using no tricks at all. (in the latest commit titled "Complete Type Safety! No Tricks!!!")
it does compile!!
... but I think it should not. ;) you probably outsmarted the compiler ;) In fact it does not compile in intellij.
The reason is that you cannot extract a Leibniz<A,B>
from (Lower_<f, ?, ?, X, Y> lower_).leib
: you theoretically only get a Leibniz<?,?>
. I think it is a javac bug for not catching it.
Even though leibX
and leibY
are not used, maybe it helps the compiler to unify CAP#1
and CAP#2
with A
and B
. In Netbeans it seems the autocomplete knew what type the final leib
was.
Edit: Actually your correct, a closer inspection reveals the final leib
to have a raw type.
@clinuxrulz but if you extract Lower.ofHkt(a.subst(new Lower(new Lower_<f, A, A, __<f, A>, __<f, A>>(Leibniz.<A>refl(), Leibniz.<__<f, A>>refl(), Leibniz.<__<f, A>>refl()))))
into an intermediate variable it does not compile anymore.
But yes, it is maybe the closer we can get to typesafe lower.
new Lower
--> new Lower<>
, i think thats my mistake
OK. I when back to helper type variables. It type checks, no additional type cast, but it may not pass the HKT processor test.
I was looking at the source for the HTK processor and the last version will fail the test. I might close this for now. Is there a way to work out for sure if Java type constructors are injective?
I've got an implementation of
lower
, it uses inheritance to achieve atype
(betweenLower
andLower_
).Not sure if it is cheating the type-system.