allsame([]).
allsame([X]).
allsame([X,X|Z]) :- allsame([X|Z])
member(M, [M|X]). member(M, [X|T]) :- member(M, T).
member(X,[3,4,5]),member(X,[4])
/ \
X = 3 member(X,[4,5]),member(X,[4])
| / \
member(3,[4]) X = 4
/ \ |
fail member(3,[]) |
/ \ |
fail fail member(4,[4])
/ \
success
Let f be the identity function, f(x) = x. Its type if
ANYTHING -> ANYTHING. If you say y = f(x), then the programmer
knows that y and x have the same type, but the compiler does not
know that. So the programmer must defeat the type system,
telling the compiler to treat y as having the same type as x.
For example, a program might say
int x;
...
y = (int)f(x);
telling the compiler information (that f(x) should have type int)
that it cannot glean from the type of f. Type variables
would allow the compiler to infer that y must have the same
type as x.
f: (A,[B]) -> [B]
where A and B are type variables.
filter: (A -> boolean) -> ([A] -> [A])
where A is a type variable.