type NegSig<Exp> = { Neg : Exp -> Exp };
when implementing two methods (double and eval) at the same time, instead of writing interfaces as IEvalDouble', we should make it more precise, IEvalDouble
NegSig<IEvalDouble> = { Neg : IEvalDouble -> IEvalDouble }
evalDoubleNeg (self: NegSig<IEvalDouble>) : NegSig<IEvalDouble> = {
Neg (e : IEvalDouble) = fold [IEval]
{ eval = (unfold [IEval] e).eval * -1 }
-- Note that this works because
-- x : IEvalDouble = IEval & IDouble <: IEval
-- Remark: since here we are dealing with positive subtyping
-- it is fine to use "NegSig<IEvalDouble'>"
-- due to recursive subtyping
& fold [IDouble] { double = self.Neg (unfold [IEvalDouble'] e).double }
-- note here: IEvalDouble' seems necessary,
-- since only unfold [recursive type] is allowed in the syntax
-- and we would require IEvalDouble <: IEvalDouble'
-- type checking:
-- e : IEvalDouble <: IEvalDouble'
-- (unfold [IEvalDouble'] e).double : IEvalDouble'
-- self.Neg : IEval & IDouble -> IEval & IDouble
-- here we need the subtyping IEvalDouble' <: IEvalDouble to hold
-- which does not typically hold for negative types!
-- expected? binary method composition + self reference ==> problem?
--
-- self.Neg (unfold [IEvalDouble] e).double : IEval & IDouble
-- <: IDouble
-- so the fold [IDouble] { double : IDouble } gets the desired type
-- the overall type of the evalDoubleNeg body:
-- IEval & IDouble
-- the overall type of the evalDoubleNeg:
-- {Neg : IEvalDouble -> IEvalDouble}