Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 类似于(>;=)但返回不同单子的函数_Haskell_Monads - Fatal编程技术网

Haskell 类似于(>;=)但返回不同单子的函数

Haskell 类似于(>;=)但返回不同单子的函数,haskell,monads,Haskell,Monads,(>>=)的类型为 (>>=) :: Monad m => m a -> (a -> m b) -> m b 我想要一个具有以下类型的函数: (Monad m, Monad n) => m a -> (a -> n b) -> n b 此函数可用于将不同的单子链接在一起 当我试图从命令行参数-p3000获取3000时,我遇到了这个问题: main = getArgs >>= (\args -> (elemIndex

(>>=)
的类型为

(>>=) :: Monad m => m a -> (a -> m b) -> m b
我想要一个具有以下类型的函数:

(Monad m, Monad n) => m a -> (a -> n b) -> n b
此函数可用于将不同的单子链接在一起

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

main = getArgs >>= (\args -> (elemIndex "-p" args) >>= (\id -> warpDebug (fromIntegral.read (args !! (id+1))) Ilm))
这显然无法编译,因为
getArgs
返回一个
IO[String]
,而
elemIndex
返回一个
Maybe Int
。上述类型的函数可用于优雅地解决此问题。我的问题是:

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

    • 这样的功能不存在。事实上,如果您将
      n
      作为标识单子,它将允许您构造一个函数
      ma->a
      ,这显然不能为所有单子定义

      为了解决“组合”两个单子的一般问题,您可以研究


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

      这个函数不存在,因为它对所有monad都没有意义。它基本上相当于一个monad解包函数
      monad m=>ma->a
      ——唯一的区别是您可以立即将它放入另一个monad中

      之所以没有为所有单子定义此函数,是因为它对其中一些单子没有意义。例如,以
      Maybe
      为例:解包的唯一方法是在没有
      的情况下抛出一个错误,并且运行时错误被忽略。一个更极端的例子是
      IO
      ——使用一个可以“解包”
      IO
      值的函数会导致奇怪的、潜在的不确定性行为

      因此,您通常没有这样的功能。然而,很多特定的单子都有这样的函数。一个很好的例子是
      runST
      ;这实际上是一种处理国家问题的安全方法。实际上,对于
      可能
      IO
      (分别是
      fromJust
      unsafePerformIO
      ),您确实有这样的函数,但它们存在我上面概述的问题,您应该避免它们

      那么,你的问题的解决办法就是看看,对于你正在处理的单子,是否存在这样一个函数。如果有,检查任何潜在的陷阱——它是否会产生运行时错误或导致奇怪的行为


      在您的情况下,如果您完全确定
      可能
      从来都不是
      ,请使用
      fromJust
      。然而,这通常不是一个好的实践,因此您应该坚持使用模式匹配
      Maybe

      的值。答案取决于您是否需要同时使用Maybe和IO monad,还是单独使用

      如果您需要同时使用它们-答案是您需要通过构建包含IO monad和MaybeT monad transformer的monad transformer堆栈来组合
      IO
      Maybe
      monad

      如果您需要单独使用,则可以使用更简单的解决方案:

      import System.Environment
      import Data.List
      
      main = getArgs >>= (\args -> return (elemIndex "-p" args 
          >>= \y -> return $ y + 900) >>= print)
      
      注意
      返回值
      。因此,您在内部parentneses中有
      可能
      单子(介于
      elemIndex
      900
      之间),但没有IO。也就是说,您不能在离开monad之前执行IO操作,正如我在print中所显示的那样