+
+ @Override
+ public int hashCode(int hash) {
+ hash = HashCodeUtils.updateWithPreprocessedValue(hash, FUN_HASH);
+ hash = domain.hashCode(hash);
+ hash = effect.hashCode(hash);
+ hash = range.hashCode(hash);
+ return hash;
+ }
+
+ @Override
+ public int hashCode(int hash, TVar[] boundVars) {
+ hash = HashCodeUtils.updateWithPreprocessedValue(hash, FUN_HASH);
+ hash = domain.hashCode(hash, boundVars);
+ hash = effect.hashCode(hash, boundVars);
+ hash = range.hashCode(hash, boundVars);
+ return hash;
+ }
+
+ @Override
+ public int skeletonHashCode(int hash) {
+ hash = HashCodeUtils.updateWithPreprocessedValue(hash, FUN_HASH);
+ hash = domain.skeletonHashCode(hash);
+ hash = range.skeletonHashCode(hash);
+ return hash;
+ }
+
+ @Override
+ public int skeletonHashCode(int hash, TVar[] boundVars) {
+ hash = HashCodeUtils.updateWithPreprocessedValue(hash, FUN_HASH);
+ hash = domain.skeletonHashCode(hash, boundVars);
+ hash = range.skeletonHashCode(hash, boundVars);
+ return hash;
+ }
+
+ public Type getCanonicalDomain() {
+ if(domain instanceof TMetaVar)
+ domain = domain.canonical();
+ return domain;
+ }
+
+ public Type getCanonicalEffect() {
+ if(effect instanceof TMetaVar)
+ effect = effect.canonical();
+ return effect;
+ }
+
+ public Type getCanonicalRange() {
+ if(range instanceof TMetaVar)
+ range = range.canonical();
+ return range;
+ }
+
+ @Override
+ public boolean equalsCanonical(Type other) {
+ if(this == other)
+ return true;
+ if(!other.getClass().equals(TFun.class))
+ return false;
+ TFun fun = (TFun)other;
+ return getCanonicalDomain().equalsCanonical(fun.getCanonicalDomain())
+ && getCanonicalEffect().equalsCanonical(fun.getCanonicalEffect())
+ && getCanonicalRange().equalsCanonical(fun.getCanonicalRange());
+ }
+
+ @Override
+ public Kind getKind(Environment context) {
+ return Kinds.STAR;
+ }
+
+ @Override
+ public Type[] skeletonCanonicalChildren() {
+ return new Type[] {Skeletons.canonicalSkeleton(domain), Skeletons.canonicalSkeleton(range)};
+ }