Haskell 提取嵌套的一元结果:m(ma)->ma

Haskell 提取嵌套的一元结果:m(ma)->ma,haskell,monads,functor,applicative,Haskell,Monads,Functor,Applicative,我有一个函数 parseArgs :: [String] -> StdGen -> IO () 它选择要运行的函数。主楼看起来像 main = parseArgs <$> getArgs <*> getStdGen >>= id 我遇到的问题是,parseArgs getArgs getStdGen的类型是IO IO,我使用类型为Monad m=>m b->m b的>>=id来提取IO。只有单行函数时,有没有办法避免提取值?最简单的方法是使用j

我有一个函数

parseArgs :: [String] -> StdGen -> IO ()
它选择要运行的函数。主楼看起来像

main = parseArgs <$> getArgs <*> getStdGen >>= id

我遇到的问题是,parseArgs getArgs getStdGen的类型是IO IO,我使用类型为Monad m=>m b->m b的>>=id来提取IO。只有单行函数时,有没有办法避免提取值?

最简单的方法是使用join:

在哪里

或者只是使用一个do

main = do
    args <- getArgs
    gen  <- getStdGen
    parseArgs args gen

最简单的方法是使用join:

在哪里

或者只是使用一个do

main = do
    args <- getArgs
    gen  <- getStdGen
    parseArgs args gen

您可以为此定义运算符:

infixl 4 <&>

(<&>) :: Monad m => m (a -> m b) -> m a -> m b
f <&> x = f >>= (x >>=)
然后你就可以写了

fx :: Monad m => m b
fx = f <$> x1 <*> x2 <*> ... <&> xn

您可以为此定义运算符:

infixl 4 <&>

(<&>) :: Monad m => m (a -> m b) -> m a -> m b
f <&> x = f >>= (x >>=)
然后你就可以写了

fx :: Monad m => m b
fx = f <$> x1 <*> x2 <*> ... <&> xn

您可以将参数配对并通过单个绑定:

main = uncurry parseArgs =<< (,) <$> getArgs <*> getStdGen
这避免了从嵌套IO中提取。诚然,它并不短,但我发现它更容易思考


它符合doTheWork=的一般模式。您可以将参数配对并通过单个绑定:

main = uncurry parseArgs =<< (,) <$> getArgs <*> getStdGen
这避免了从嵌套IO中提取。诚然,它并不短,但我发现它更容易思考


它符合doTheWork=的一般模式。难道您还没有一个单行函数吗?我正在寻找一种方法来避免提取,这是由>>=id函数完成的。我可以问一下您为什么要避免使用>>=id吗?如果您使用的是Monad m=>m m a->m a约束,这似乎是最好的方法,因为其他一些解决方案可能有应用程序m、Monad m等,这在上下文中没有什么意义。@AJFarmar我并没有特别避免>>=id,而是避免任何进行提取的要求。看来那是不可能的。这并不重要,因为所有这些都只是为了学习。难道你还没有一个单行函数吗?我正在寻找一种方法来避免提取,这是由>>=id函数完成的。我可以问一下你为什么要避免使用>>=id吗?如果您使用的是Monad m=>m m a->m a约束,这似乎是最好的方法,因为其他一些解决方案可能有应用程序m、Monad m等,这在上下文中没有什么意义。@AJFarmar我并没有特别避免>>=id,而是避免任何进行提取的要求。看来那是不可能的。这并不重要,因为所有这些都是纯粹为了学习的目的。很显然,加入和我做的完全一样。但它仍然没有回答这个问题。是否可能?@Seig问题是,有没有一种方法可以避免在只有一行函数的情况下需要值的'extraction'>>=id?这个问题的答案是肯定的,使用join。您是否希望现有的组合器具有Monad m=>a->b->mr->ma->mb->mr类型?在Hoogle上快速搜索不会得到任何结果,我认为join将是实现这一点的惯用方法。好吧,这就实现了。main=join$liftM2 parseArgs getArgs getStdGen你怎么会喜欢这个@或者,它只需要1次导入,并且使用更少的运算符和符号。说真的,我更喜欢做记号,因为这很明显发生了什么,但是如果让我在前两种方法中做出选择,我会选择完全一元的方法,而不是一元和应用的方法。但这都是我的看法,我当然不认为第一个是错误的。很显然,加入和我做的完全一样。但它仍然没有回答这个问题。是否可能?@Seig问题是,有没有一种方法可以避免在只有一行函数的情况下需要值的'extraction'>>=id?这个问题的答案是肯定的,使用join。您是否希望现有的组合器具有Monad m=>a->b->mr->ma->mb->mr类型?在Hoogle上快速搜索不会得到任何结果,我认为join将是实现这一点的惯用方法。好吧,这就实现了。main=join$liftM2 parseArgs getArgs getStdGen你怎么会喜欢这个@或者,它只需要1次导入,并且使用更少的运算符和符号。说真的,我更喜欢做记号,因为这很明显发生了什么,但是如果让我在前两种方法中做出选择,我会选择完全一元的方法,而不是一元和应用的方法。但这都是我的看法,我当然不认为第一个是错误的。
main = uncurry parseArgs =<< (,) <$> getArgs <*> getStdGen