I have this function:
isUndefined :: () -> Bool
isUndefined x = case unsafePerformIO $ (try (return $! x) :: IO (Either SomeException ())) of
Left _ -> True
Right _ -> False
then:
isUndefined () = False
isUndefined undefined = True
Solving the halting problem. Of course, this can be extended to other types too.
My question: how is this possible? Is Control.Exception.try
really breaking things here?
unsafePerformIO
is breaking things here. In GHC,undefined
simply raises an exception rather than looping forever (which would be unhelpful). Exceptions are not meant to be caught in pure (non-IO) code -- indeed the type system indeed prevents you to attempt as much.By using
unsafe*
functions, you are telling GHC "ignore everything, I know what I'm doing", and all the safety belts are now off. Do yourself a favour and pretend thatunsafe*
stuff does not exist.