In Haskell, you can throw an exception from purely functional code, but you can only catch in IO code.
The paper delnan mentions in the comments, and the answers to this previous question, certainly provide sufficient reasons for only catching exceptions in IO.
However, I can also see why reasons such as observing evaluation order or breaking monotonicity may not be persuasive on an intuitive level; it's difficult to imagine how either could cause much harm in the vast majority of code. As such, it might help to recall that exception handling is a control flow structure of a distinctly non-local variety, and being able to catch exceptions in pure code would allow (mis)using them for that purpose.
Allow me to illustrate exactly what horror this entails.
First, we define an exception type to use, and a version of catch that can be used in pure code:
newtype Exit a = Exit { getExit :: a } deriving (Typeable)
instance Show (Exit a) where show _ = "EXIT"
instance (Typeable a) => Exception (Exit a)
unsafeCatch :: (Exception e) => a -> (e -> a) -> a
unsafeCatch x f = unsafePerformIO $ catch (seq x $ return x) (return . f)
This will let us throw any Typeable value and then catch it from some outer scope, without the consent of any intervening expressions. For instance, we could hide an Exit throw inside something we pass to a higher-order function to escape with some intermediate value generated by its evaluation. Astute readers may have figured out by now where this is going:
callCC :: (Typeable a) => ((a -> b) -> a) -> a
callCC f = unsafeCatch (f (throw . Exit)) (\(Exit e) -> e)
Yes, that actually works, with the caveat that it requires any use of the continuation to be evaluated whenever the whole expression is. Keep that in mind if you try this out, or just use deepseq if nuking from orbit is more your speed.
Behold:
-- This will clearly never terminate, no matter what k is
foo k = fix (\f x -> if x > 100 then f (k x) else f (x + 1)) 0
But:
∀x. x ⊢ callCC foo
101
Escaping from inside a map:
seqs :: [a] -> [a]
seqs xs = foldr (\h t -> h `seq` t `seq` (h:t)) [] xs
bar n k = map (\x -> if x > 10 then k [x] else x) [0..n]
Note the need to force evaluation.
∀x. x ⊢ callCC (seqs . bar 9)
[0,1,2,3,4,5,6,7,8,9]
∀x. x ⊢ callCC (seqs . bar 11)
[11]
...ugh.
Now, let us never speak of this again.