I've had a lot of success in my own language designs with dividing the problem into two cases, equality and identity, or EQUALP and EQ in CL lingo. Despite having written a ton of CL over the years, I still fail to remember the specifics of EQL & EQUAL. Defaulting to full value equality does come with a performance cost, but I feel like we're mostly past the point where we should waste precious time on these kinds of micro optimizations for most use cases.
I agree at least separating identity and equality seem to be important in practice. I'm not completely sold on where the other lines should be.
I don't love the CL implementation, particular eql vs equalp on numerics seems fiddly, and it's hard to keep all the cases separate. Homoiconicity introduces the need for a "representation equality" i guess which isn't always needed, etc.
https://github.com/codr7/gfoo