package nl.utwente.viskell.haskell.expr; import com.google.common.collect.ImmutableList; import nl.utwente.viskell.haskell.type.HaskellTypeError; import nl.utwente.viskell.haskell.type.Type; import nl.utwente.viskell.haskell.type.TypeChecker; import nl.utwente.viskell.haskell.type.TypeScope; import java.util.List; /** * Lazy application of an argument to a function. */ public class Apply extends Expression { /** * The expression to apply the argument to. */ private final Expression func; /** * The argument to apply. */ private final Expression arg; /** * Applies an argument to a function to produce a new expression. The application is lazy, the type needs to be * analyzed before there is certainty about the validity of this application and the resulting type. * * @param func The expression to apply argument to. * @param arg The argument to apply. */ public Apply(final Expression func, final Expression arg) { this.func = func; this.arg = arg; } @Override public final Type inferType() throws HaskellTypeError { final Type funcType = func.inferType(); final Type argType = arg.inferType(); final Type resType = TypeScope.unique("b"); // Rule [App]: // IFF the type of our function is a -> b and the type of our arg is a // THEN the type of our result is b TypeChecker.unify(this, funcType, Type.fun(argType, resType)); return resType; } @Override public final String toHaskell() { return String.format("(%s %s)", this.func.toHaskell(), this.arg.toHaskell()); } @Override public final String toString() { return String.format("(%s %s)", this.func.toString(), this.arg.toString()); } @Override public final List<Expression> getChildren() { return ImmutableList.of(func, arg); } }