I have a function which returns a value wrapped in a Monad,
produceMessage :: MonadIO m => KafkaProducer -> ProducerRecord -> m (Maybe KafkaError)
Run Code Online (Sandbox Code Playgroud)
And I have some code to call this function like so
err <- produceMessage prod message
return $ Right ()
Run Code Online (Sandbox Code Playgroud)
The above code has been written by someone else, I am just trying to understand what is happening here. This is the rest of the function
messageSender :: KafkaProducer -> String -> Config.KafkaP (Either KafkaError ())
messageSender prod msg = do
message <- mkMessage Nothing (Just $ pack msg)
err <- produceMessage prod message
--forM_ err print
return $ Right ()
Run Code Online (Sandbox Code Playgroud)
I have three specific questions,
I am confused what does the type signature of produceMessage mean? The type constraint is MonadIO m, what does this mean?
The return type is m (Maybe KafkaError), so this returns a Maybe value wrapped in which monad?
How does Right () come into picture here? In general I am really not
able to understand the last two lines of messageSender.
The type constraint means that the function can be used to return a value for any type m that has a MonadIO instance. Typically, that means IO itself or a monad stack built on top of IO.
The value returned by produceMessage is in part determined by the caller. Need an IO (Maybe KafkaError) value? You can get that, because IO has a MonadIO instance. Need a MyCustomMonadStack (Maybe KafkaError)? You can get that, if you define a MonadIO instance for MyCustomMonadStack.
Presumably, Config.KafkaP also has a MonadIO instance, based on how messageSender uses produceMessage.
messageSender has a return value of Config.KafkaP (Either KafkaError ()). The expression return $ Right () first uses Right () to produce a value of type Either KafkaError (), then return is applied to that to produce a value of type Config.KafkaP (Either KafkaError ()). Note that the commented line -- forM_ err print is the only thing that might have used the value coming from produceMessage, so right now messageSender pretends that produceMessage worked, whether it did or not.
一个更可靠的定义实际上produceMessage将以某种方式使用返回值,例如
err <- produceMessage prod message
return $ case err of
Nothing -> Right ()
Just theError -> Left theError
Run Code Online (Sandbox Code Playgroud)