You have two options:
- Encode your preconditions in your types so that they're checked at compile-time.
- At run-time check that your preconditions hold so that your programs stops before doing something nasty and unexpected. Gabriel Gonzales shows this in detail his answer
Option 1. is of course preferred, but it's not always possible. For example, you can't say in Haskell's type systems that one argument is greater than other one, etc. But still you can express a lot, usually much more than in other languages. There are also languages that use so called dependent types and which allow you to express any condition in their type system. But they're mostly experimental or research work. If you're interested, I suggest you to read book Certified Programming with Dependent Types by Adam Chlipala.
Doing run-time checks is easier and it's what programmers are more used to. In Scala you can use require
in your methods and recover from the corresponding exception. In Haskell this is trickier. Exceptions (caused by failing pattern guards, or issued by calling error
or undefined
) are by their nature IO
based, so only IO
code can catch them.
If you suspect that your code can fail for some reasons, it's better to use Maybe
or Either
to signal failures to the caller. The drawback is that this will make the code more complex and less readable.
One solution is to embed your computations into an error handling/reporting monad, such as MonadError
. Then you can report errors cleanly and catch them somewhere at a higher level. And if you're already using a monad for your computations, you can just wrap your monad into EitherT
transformer.