     @warn_unused_result public func applying<T, V>(function: (T -> V), lazily: Bool = false) -> Term {
         return applying({ (untypedArgument: Any) throws -> Any in
             guard let argument = untypedArgument as? T else {
-                throw EvaluationError.dynamicCastArgumentFailure
+                throw EvaluationError.dynamicCastFailure(purpose: .result, value: untypedArgument, targetType: T.self)
             }
             return function(argument)
         }, lazily: lazily)

//

public enum EvaluationError: ErrorType, CustomStringConvertible {
    case lambdaResult(Term)
    case boundResult(Binding)
    case expectedConstantFunction(Any)
    case dynamicCastFailure(Any, Any.Type)
    case dynamicCastArgumentFailure // TODO
    
    // TODO: These are bad errors
    public var description: String {
        switch self {
        case .lambdaResult(let lambda):
            return "The result of the evaluation was unexpectedly a lambda: `\(lambda)`"
        case .boundResult(let binding):
            return "The result of the evaluation was unexpectedly a bound variable: `\(binding)`"
        case .expectedConstantFunction(let term):
            return "Expected constant function on left hand side of application, but found `\(term)`"
        case .dynamicCastFailure(let value, let type):
            return "Unable to cast `\(value)` from type `\(value.dynamicType)` to type `\(type)`)"
        case .dynamicCastArgumentFailure:
            return "Dynamic cast argument failure"
        }
    }
}

        switch term {
        case .constant(let untypedValue):
            guard let value = untypedValue as? V else {
                throw EvaluationError.dynamicCastFailure(purpose: .argument, value: untypedValue, targetType: V.self)
            }
            return value
        case .application(let lhs, let rhs):
            let (untypedFunction, argument): (Any, Any) = (try lhs.evaluated(), try rhs.evaluated())
            
            typealias AnyFunction = Any throws -> Any
            guard let function = untypedFunction as? AnyFunction else {
                throw EvaluationError.dynamicCastFailure(purpose: .function, value: untypedFunction, targetType: AnyFunction.self)
            }
            return try Term.constant(function(argument)).evaluated()
        case .variable, .lambda:
            throw EvaluationError.expectedConstant(found: term)
        }
    }
}
