Languages like C, Haskell, Lisp, Smalltalk, and assembly language are often touted as things every programmer should know for their effect on the way one thinks about programming, even if they're used very little in real world situations. However, to really learn a language in depth to the point where you know not only the syntax and semantics but libraries, idioms, all of the relatively obscure features and dark corners, etc. and can get real work done in it requires a pretty serious time commitment.
When dealing with languages like the above, at what level of depth do you start to get to a point of diminishing returns? For example, if you're learning C just to expand your horizons, is it ok to stop when you feel you have a pretty good handle on how pointers work and what it's like to manage memory manually, or do you need to do a serious project or two? When learning assembly language, do you need to be proficient in writing it, or does being able to understand its structure and recognize common idioms from higher level languages, like loops, virtual function calls, stack variables, pointer dereferences, etc. count as "knowing" assembly language? More generally, is it important to learn the whole language, or just to thoroughly wrap your head around the concepts that make it different from more mainstream languages?
This is about my level of knowledge of C and assembly language respectively. Haskell and Lisp are next on my agenda. Are these reasonable depths of knowledge for C and assembler? What are similar benchmarks for Haskell and Lisp?