类型(>>=)是
(>>=) :: Monad m => m a -> (a -> m b) -> m b
Run Code Online (Sandbox Code Playgroud)
我想要一个具有以下类型的函数:
(Monad m, Monad n) => m a -> (a -> n b) -> n b
Run Code Online (Sandbox Code Playgroud)
此函数可用于将不同的monad链接在一起.
当我试图3000从命令行参数中获取时,我遇到了这个问题-p 3000:
main = getArgs >>= (\args -> (elemIndex "-p" args) >>= (\id -> warpDebug (fromIntegral.read (args !! (id+1))) Ilm))
Run Code Online (Sandbox Code Playgroud)
这显然不会编译,因为getArgs返回IO [String]并elemIndex返回a Maybe Int.可以使用上述类型的功能来优雅地解决该问题.我的问题是:
此功能不存在,因为它对所有monad都没有意义.它基本上相当于monad解包功能Monad m => m a -> a- 唯一的区别是你马上把它放到另一个monad中.
没有为所有monad定义此函数的原因是因为它对其中一些没有意义.例如,take Maybe:解压缩它的唯一方法就是抛出错误(如果有的话)Nothing,并忽略运行时错误.一个更极端的例子是 - IO使用一个可以"解包" IO值的函数会导致奇怪的,可能是非确定性的行为.
因此,您通常没有这样的功能.然而,许多特定的monad 确实带有这样的功能.一个很好的例子是runST; 这实际上是一种处理国家的安全方式.你实际上确实有这两个Maybe和IO(fromJust和unsafePerformIO分别)的功能,但它们有我上面概述的问题,你应该避免它们.
那么,问题的解决方案是查看是否存在这样一个函数,用于处理您正在处理的任何monad.如果有,请检查任何潜在的陷阱 - 它是否会产生运行时错误或导致奇怪的行为?
在您的情况下,如果您绝对确定Maybe永远不会Nothing,请使用fromJust.但是,这通常不是很好的做法,所以你应该坚持模式匹配的价值Maybe.