Hope (not HOPE) was a clever functional programming language designed by Rod Burstall, named after Hope Park Square, where his office was located in Edinburgh (Hope Park Square was named after a civil engineer who greatly improved that area of Edinburgh, by draining a swamp, among other things). Its pattern matching feature, which led to that of ML, was in part inspired by discussions between Burstall and Goguen about OBJ, which was also under development during the same period; this explains the similarity between pattern matching in ML and in OBJ.
OBJ, like the original version of Clear, used equations to define recursive functions. The patterns allowed in these definitions are more general than those of ML, and in particular, repeated variables are allowed, so that the following is good OBJ code for the function strip on page 350 of Sethi, although it is not permitted in ML:
op strip : Elt List -> List . vars A B : Elt . var L : List . eq strip(A, ) =  . eq strip(A, A :: L) = strip(A, L) . eq strip(A, B :: L) = B :: L if A =/= B .where Elt and List are polymorphic types, the latter being for lists of the former. (Note that the third equation above corrects a bug in the third equation for strip on page 350 of Sethi.) Personally, I find the equational syntax simpler and clearer.
OBJ also allows matching modulo associativity and/or commutativity. For example, if we define
op _+_ : Nat Nat -> Nat [comm] . vars M N : Nat . eq M + 0 = M . eq M + s N = s(M + N).then the first equation can match
0 + s s 0and the second can match
(s x) + y, returning
s s 0and
s(x + y), respectively. When the leftside has a single instance of a binary commutative operation, one can think of commutative pattern matching as replacing the single equation by two equations, one the original, and the other with the two arguments of the operation switched, e.g., in this case we get
eq M + 0 = M . eq 0 + M = M . eq M + s N = s(M + N). eq s N + M = s(M + N).However, more complex patterns with commutative operations cannot be explained so simply. Matching modulo associativity and/or commutativity differs even more dramatically from ML pattern matching.
You can find the full OBJ code for these two examples, as well as several others, at obj.html, along with copies of the OBJ output for these examples, and a link to detailed documentation and many more examples; several examples demonstrate the powerful OBJ module system.
It is interesting to think about not just how, but also why ML and OBJ are different: ML is intended primarily as a programming language, and so must have a good compiler, whereas OBJ is intended primarily for specification, verification, and prototyping, and secondarily for programming. This implies that it should be as expressive as possible, but with a strict logical basis. For this reason, OBJ is interpreter based (it does not have a compiler), which allows much greater flexability in its pattern matching and module system, while still preserving its logical purity (no side effects). OBJ is a logical programming language, in the sense that all its computations are proofs in its underlying logical system, which is equational logic, based on the substitution of equals for equals. ML has a pure subset based on the lambda calculus of higher order functions, but it also adds a number of impure features (such as its exception mechanism) to make it more suitable for programming. (OBJ also handles exceptions, but in a very different way that is purely logic based.) We will see that Prolog is similar to ML in that it is primarily for programming, has a good compiler, and sacrifices some purity to enhance its utility for programming.