我有一个功能
parseArgs :: [String] -> StdGen -> IO ()
选择要运行的函数。主要看起来像
main = parseArgs <$> getArgs <*> getStdGen >>= id
我遇到的问题parseArgs <$> getArgs <*> getStdGen
的类型为IO (IO ())
,我使用类型为(>>= id)
的{{1}}提取。有没有办法避免在只有一行函数的情况下“提取”值?
答案 0 :(得分:4)
最简单的方法是join
:
main = join $ parseArgs <$> getArgs <*> getStdGen
就个人而言,我更喜欢表格
main = join $ liftM2 parseArgs getArgs getStdGen
,其中
join :: Monad m => m (m a) -> m a
liftM2 :: Monad m => (a -> b -> r) -> m a -> m b -> m r
或者只使用do
main = do
args <- getArgs
gen <- getStdGen
parseArgs args gen
答案 1 :(得分:3)
您可以为此定义运算符:
infixl 4 <&>
(<&>) :: Monad m => m (a -> m b) -> m a -> m b
f <&> x = f >>= (x >>=)
如果您有类型
的功能f :: Monad m => (a1 -> a2 -> ... -> an -> m b) -> m a1 -> m a2 -> ... -> m an -> m b
然后你可以写
fx :: Monad m => m b
fx = f <$> x1 <*> x2 <*> ... <&> xn
其中每个xi
的类型为m ai
。
在你的情况下,它只是
parseArgs <$> getArgs <&> getStdGen
答案 2 :(得分:2)
您可以将参数配对并将它们放在一个绑定中:
main = uncurry parseArgs =<< (,) <$> getArgs <*> getStdGen
这可以避免从嵌套IO中提取。不可否认,这并不短,但我觉得更容易思考。
它符合doTheWork =<< getAllTheInputs
的一般模式,如果代码更复杂,这可能是你最终安排事情的方式。