You might use catch
from Control.Exception as in
import Prelude hiding (catch)
import Control.Exception
main = do
print answer `catch` errorMessage
where
errorMessage :: SomeException -> IO ()
errorMessage = putStrLn . ("error: " ++) . show
Catching SomeException
is sloppy, and the output is messy:
[error: No cycle
It got partway through printing an array but ran into the exception. Not very nice.
Another answer has covered the fine approach of using the Maybe
monad for representing computations that can fail. An even more general approach is MonadError
:
{-# LANGUAGE FlexibleContexts #-}
import Control.Applicative
import Control.Monad.Error
detec2 :: (MonadError String m, Eq a) => [a] -> Int -> m Int
detec2 ys n | 2*n >= (length ys) = throwError "No cycle"
| t == h = return (2*n - n)
| otherwise = detec2 ys (n+1)
where
t = ys !! n
h = if n == 0 then ys !! 1 else ys !! (n*2)
(Notice this also fixes the bug in your first guard that allows !!
to throw exceptions.)
This permits similar but more flexible use, for example:
answer2 = f2 <$> [1/x | x <- [1..100]]
f2 x = detec2 (show x) 0
main = do
forM_ answer2 $
\x -> case x of
Left msg -> putStrLn $ "error: " ++ msg
Right x -> print x
Now the first few lines of the output are
error: No cycle
error: No cycle
2
error: No cycle
error: No cycle
3
6
error: No cycle
2
Keep in mind this is still a pure function: you don't have to run it inside IO
. To ignore the no-cycle errors, you might use
cycles :: [Int]
cycles = [x | Right x <- answer2]
If you don't care about errors messages at all, then don't generate them. A natural way to do this is with lists where you return the empty list for no cycles and condense the result with concatMap
:
detec3 :: (Show a) => a -> [Int]
detec3 x = go 0
where go :: Int -> [Int]
go n
| 2*n >= len = []
| t == h = [2*n - n]
| otherwise = go (n+1)
where t = ys !! n
h | n == 0 = ys !! 1
| otherwise = ys !! (n*2)
len = length ys
ys = show x
main = do
print $ concatMap (detec3 . recip) [1..100]
Finally, you may be interested in reading 8 ways to report errors in Haskell.