【问题标题】:How to deal with a monadic return value `m (Maybe Foo)`?如何处理一元返回值`m (Maybe Foo)`?
【发布时间】:2019-03-23 04:11:05
【问题描述】:

我有一个函数,它返回一个包裹在 Monad 中的值,

produceMessage :: MonadIO m => KafkaProducer -> ProducerRecord -> m (Maybe KafkaError)

我有一些代码可以像这样调用这个函数

err <- produceMessage prod message
return $ Right ()

上面的代码是别人写的,我只是想了解这里发生了什么。这是函数的其余部分

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 ()

我有三个具体问题,

  1. 我很困惑produceMessage 的类型签名是什么意思?类型约束为MonadIO m,这是什么意思?

  2. 返回类型是m (Maybe KafkaError),所以这会返回一个包裹在哪个monad中的Maybe值?

  3. Right () 是如何出现在这里的?总的来说我真的不是 能够看懂messageSender的最后两行。

【问题讨论】:

    标签: haskell monads


    【解决方案1】:

    类型约束意味着该函数可用于返回具有MonadIO 实例的任何类型m 的值。通常,这意味着 IO 本身或构建在 IO 之上的 monad 堆栈。

    produceMessage 返回的值部分由调用者决定。需要IO (Maybe KafkaError) 值吗?你可以得到它,因为IO 有一个MonadIO 实例。需要MyCustomMonadStack (Maybe KafkaError)?如果你为MyCustomMonadStack 定义一个MonadIO 实例,你可以得到它。

    根据messageSender 使用produceMessage 的方式,推测Config.KafkaP 也有一个MonadIO 实例。

    messageSender 的返回值为Config.KafkaP (Either KafkaError ())。表达式return $ Right () 首先使用Right () 生成Either KafkaError () 类型的值,然后将return 应用于that 以生成Config.KafkaP (Either KafkaError ()) 类型的值。请注意,注释行-- forM_ err print 是唯一可能使用来自produceMessage 的值的东西,所以现在messageSender 假装produceMessage 有效,不管它是否有效。

    一个更健壮的定义实际上会以某种方式使用produceMessage 的返回值,也许像

    err <- produceMessage prod message
    
    return $ case err of
               Nothing -> Right ()
               Just theError -> Left theError
    

    【讨论】:

    • 感谢您的精彩解释。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-18
    相关资源
    最近更新 更多