I think it's easier to get if you match a pattern to some text by hand, taking a simple pattern like ^a+bc$ and trying to see if it matches:
Here are a few test cases:
"aaaaaaaaabbbc" ?
1) ^a+ means it starts with 1 or more 'a's, so those eat all my 'a's and I'm matching bbbcc against 'bc' now 2) b* means 0 or more 'b's; those eat up everything but the c at the end. 3) c$ matches exactly one c at the end, so yeah, we have a match. If there had been one more c (or anything else), the match would fail because it wouldn't hit the $ (which is end of string).
aaac ?
1) ^a+ eats all the 'a's again. 2) b* ... what b? It's "zero or more" so yes, we can skip it. 3) c$ Yes, there's one c at the end. We have a match.
bc ?
1) We need one* or more 'a's at the start. That's the difference between + and . Match fails immediately.
acbbc ?
1) ^a+ matches the a. 2) b means it's optional, so we don't fail... yet. But we don't match anything, either. 3) c$ That c matches, but we're not at the end of the string yet. There's still "bbc" left to match and we're out of pattern. Fail.
You can do something similar with the tools other people have linked in comments. This was just to give an example pattern and a few test cases to get you started.
It's weird, though. Even though this clicks for me, I don't feel like I get monads at all. Yeah, I've read the 3 monad laws (great... so something being a monad means that I can monad it, un-monad it and do something vaguely similar to composition on monads) and I can do some very simple Lisp which uses built-in stuff they say is built from monads (like printing). But I don't know how they work internally at all, or how they're fundamentally different from all the other Lisp statements ("causes side affects" isn't terribly specific... why is printing to the screen a side effect? Is setq a monad?).
In other words, there's probably some topic for every programmer that they really have to struggle with. As easily as regexes come to me, I struggle to understand other stuff.
I've been at it for quite a while, incidentally. But I'm not going to give up any time soon. So keep working on it.
It does help, but I think there's still a lot I don't know. I mean, 'bind' and 'return' still seem like the names are backwards to me. Somehow, I feel like 'return' should give me a value, rather than shoving a value into a monad. But that's probably because I'm used to C and its relatives.
Perhaps I simply need to read up more on FP itself. I have a huge bookshelf full of half-read books (and yes, plenty of fully-read books) but nowhere near enough free time...
http://weitz.de/regex-coach/ - It's Windows only though
There are many others, but his one thought me quite a lot
also, python's regex module can show you how it interprets a regular expression by passing the re.DEBUG flag to re.compile:
>>> import re
>>> re.compile('a*b+', re.DEBUG)
max_repeat 0 65535
literal 97
max_repeat 1 65535
literal 98
<_sre.SRE_Pattern object at 0x100460230>