haskell - 类似于 (>>=) 的函数,但返回不同的 monad

标签 haskell monads

(>>=) 的类型是

(>>=) :: Monad m => m a -> (a -> m b) -> m b

我想要一个具有以下类型的函数:

(Monad m, Monad n) => m a -> (a -> n b) -> n b

此函数可用于将不同的 monad 链接在一起。

当我尝试从命令行参数-p 3000获取3000时,我遇到了这个问题:

main = getArgs >>= (\args -> (elemIndex "-p" args) >>= (\id -> warpDebug (fromIntegral.read (args !! (id+1))) Ilm))

这显然不会编译,因为 getArgs 返回一个 IO [String] 并且 elemIndex 返回一个 Maybe Int。可以使用上述类型的函数来优雅地解决这个问题。我的问题是:

  • 这个函数已经定义了吗? (Hoogle没有找到任何)
  • 如果没有,可能是由于某种原因。那到底是什么原因呢?这被认为是一种不好的做法吗?我认为这是比使用 case 表达式更好的方法。

最佳答案

这样的函数不存在。事实上,如果你将 n 作为恒等 monad,它会允许你构造一个函数 m a -> a,这显然不能为所有 monad 定义。

要解决“组合”两个 monad 的一般问题,您可以查看 monad transformers .

但是,在您的示例中使用 monad 转换器似乎有些过分了。您可以简单地定义一个函数 [String] -> Maybe Args (对于某些自定义类型 Args - 在示例中说 Int)命令行参数处理,然后从 IO monad 中对结果进行模式匹配(或使用 maybe )。

关于haskell - 类似于 (>>=) 的函数,但返回不同的 monad,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8614053/

相关文章:

haskell - 为什么 Haskell 标准库中没有 <<?

haskell - 为什么haskell的bind函数要把一个函数从非monadic变成monadic

haskell - 如何不确定地将值放入状态中?

haskell - 使用不可变数据结构改变数据

haskell - 使用组合器将管道重新分块成更大的 block

haskell - 如何避免在 Haskell 中检查空值?

haskell - 是否存在渐近优化一系列 MonadPlus 操作的 Codensity MonadPlus?

parsing - 如何在 Haskell 中查看派生实例/派生的生成代码

haskell - 为什么我注释这个类型签名的错误没有破坏东西?

Haskell 类型和模式匹配问题 : extracting fields from a data type