Many C function returns with a negative integer on failure. Different negative values might give information about the type of failure. This can not be solved with Maybe.
data Either a b = Left a | Right b
The Either type is used to represent either a value of type a constructed with the Left data constructor or a value of type b constructed with Right. It is generally used to wrap the result of a computation that might fail. By convention the Left constructor is used to represent the failure case and the Right constructor is used for the success case. The wrapped values can be extracted with pattern matching.
The following code contains a dummy algorithm, but demonstraits the idea well.
import Data.Maybe
data Message = Message {message :: Maybe String, signature :: Maybe String}
data MessageError = MissingMessage | MissingSignature | InvalidSignature deriving Show
validSignature :: Maybe String -> Maybe String -> Bool
validSignature content signature = let clen = length (fromJust content)
slen = length (fromJust signature)
lens = clen + slen
in (1 == (lens `mod` 2))
getMessageContent :: Message -> Either MessageError String
getMessageContent (Message Nothing _) = Left MissingMessage
getMessageContent (Message _ Nothing) = Left MissingSignature
getMessageContent (Message content@(Just c) signature) = if validSignature content signature
then Right c
else Left InvalidSignature
report :: Message -> String
report msg = case getMessageContent msg of
Left reason -> "Failed to get content: " ++ show reason
Right content -> "The content is: " ++ content
- Implement the following functions.
data VelocityError = TimeIsNegative | TimeIsZero | LenIsNegative deriving Show
velocity :: (Integral a) => a -> a -> Either VelocityError a
velocityReport :: Show a => Either VelocityError a -> String