So there's a library in Haskell called spoon which lets me do this
safeHead :: [a] -> Maybe a
safeHead = spoon . head
but it also lets me do this
>>> spoon True :: Maybe Bool
Just True
>>> spoon (error "fork") :: Maybe Bool
Nothing
>>> spoon undefined :: Maybe Bool
Nothing
>>> spoon (let x = x in x) :: Maybe Bool
<... let's just keep waiting...>
which seems really useful in certain cases, but it also violates denotational semantics (to my understanding) since it lets me distinguish between different things in the semantic preimage of ⊥
. This is strictly more powerful than throw
/catch
since they probably have a semantics defined by continuations.
>>> try $ return (error "thimble") :: IO (Either SomeException Bool)
Right *** Exception: thimble
So my question is: can someone use spoon maliciously to break type safety? Is the convenience worth the danger? Or, more realistically, is there a reasonable way that using it could erode someone's confidence in the meaning of a program?