Parsing a String to see if it contains another String, and then returning a monad if it does
Why do you need the element type to be a monad? The only point you require it is when you do return () in order to signal failure. I'd propose implementing a more general function

lookupSublist :: Eq a =&gt; [a] -&gt; [([a], b)] -&gt; Maybe b


Which could be implemented as:

lookupSublist xs = fmap snd . listToMaybe . filter (flip isInfixOf xs . fst)


So we first filter out all alternatives where the first element doesn't have xs as infix. Then we return the second element of the first remaining element, if any.

Some random notes on your code:


Using noEmptyList as a guard mid-expression isn't a good idea. Using error is pretty "evil" in the first place, you don't want to bury it like that. Putting the list in the where would allow you to say listenString a l | null list = error...
(\(x,_) -&gt; if (x == []) then False else True) is simply not . null . fst. I'm not quite sure why you filter for that, to be honest. Wouldn't having [] in the list be a pretty elegant way to implement a default fallback value?
I am actually quit struggling to understand the rest of your code. I am pretty sure that your usage of ListT actually hurts more than it helps - generally when you start pattern-matching on the contents of a monad you are doing something wrong. Could you explain what you tried to do?




Edit: If the position of the match end should take priority, I would propose going over the prefixes of the string and suffix-test the options:

lookupFirstSublist str opts = listToMaybe $ mapMaybe f $ inits opts
  where f s = fmap snd $ listToMaybe $ filter (flip isSuffixOf s . fst) opts