It is definitely not is_not/2. That predicate is part of must_be/2 and responsible for the error message. So, if X is not a list we call is_not(list, X) which will figure out which error to throw (basically an instantiation error or a type error).
The idea of a can_be/2 makes sense. Shouldn’t be too hard to add to library(error). If someone likes to give it a try, I’m happy to consider the PR.
It might better (?) relate to work that is sleeping for a long time and defines Prolog types as constraints. So, you can do ?- type(X, atom), type(Y, integer), X = Y. and it will fail On the other hand, this library is more intended for abstract interpretation/type checking. I assume can_be/2 is no constraint, so we can happily do this?
In the “Power of Prolog” video I linked, Markus Triska explains it as:
Silent failure for wrong types is default practice in Prolog code.
Type errors help us determine the exact location of mistakes.
However, a sound distinction between type errors and instantiation errors is hard to get right manually.
Therefore, if you want type errors, use:
must_be/2 for arguments that must be sufficiently instantiated