For terseness, it's probably hard to beat Julia:
addone1(x) = x+1
Completely generic with type inference, and compiles to optimal machine code. But it also suffers from the "latent type errors deferred to the user" that the article discusses. Calling it with a type that does not support adding 1 will raise an error for a non-existing "+" method:
addone1("0")
ERROR: MethodError: no method matching +(::String, ::Int64)
This is pretty understandable in this case, but we may prefer annotating the addone function so that it can only be called with types that support adding 1. Using the (very conservative) notion that only numbers can have 1 added to them, we could use Julia's type hierarchy to restrict the types for which addone may be called:
addone2(x::T) where T<:Number = x+1
Calling it with an incompatible type now properly points to the outer level:
addone2("0")
ERROR: MethodError: no method matching addone2(::String)
But this type of dispatch restrictions rely on a type hierarchy, causing similar problems as class hierarchies in OO languages. For example, the user might have defined their own type that supports addition but not multiplication. Using addone on this type makes sense, but the type shouldn't be a subtype of Number. Such more flexible dispatch scenarios can be achieved with traits. Although Julia currently doesn't have direct language support for traits, they can be implemented inside the language, with macros for syntactic sugar. With traits, the previous example becomes:
using SimpleTraits
@traitdef CanAddOne{T}
@traitimpl CanAddOne{T} <- issubtype(T,Number)
@traitfn addone3{T; CanAddOne{T}}(x::T) = x+1
Still relatively straight-forward to write and read, and the trait-restricted addone has the same performance as the original one. For incompatible types, the error message still points to the outer level:
addone3("0")
ERROR: MethodError: no method matching addone3(::Type{SimpleTraits.Not{CanAddOne{String}}}, ::String)
Importantly, the user can extend the CanAddOne trait (with additional @traitimpl lines) to cover their own type, without being forced to make it a subtype of Number.