将 getArgs 从 IO [String] 转换为 IO [Int]

Transform getArgs from IO [String] to IO [Int]

我想编写如下程序:

add :: Int -> Int -> Int
add a b = a + b

main :: IO ()
main = do
    args <- getIntArgs
    case args of
        [a,b] -> putStrLn $ show $ add a b

有没有一种方法可以根据 getArgs(来自 System.Environment)编写函数 getIntArgs

先在脑海中解开它。您需要一个来自 IO [String] -> IO [Int] 的函数。首先考虑一个来自 f a -> f b 的函数——嗯,那就是 fmap!

然后我们只需要找到一个来自 a -> b 的函数。在这种情况下 a ~ [String]b ~ [Int]。现在我们看到另一个函子包装了我们的具体类型——fmap 再次起作用,这次抽象出 [] 而不是 IO.

现在我们需要一个函数 String -> Int。这是 read.

getIntArgs = fmap (fmap read) getArgs

因为 f (g x) = (f . g) x,我们可以写(而且应该更喜欢,它是 Haskelly-er):(fmap . fmap) read $ getArgs.

事实上你的整个功能只是:

main :: IO ()
main = (fmap (sum . fmap read) getArgs) >>= print
-- assuming you're okay replacing `(+)` with `sum`

-- if not:
main = (fmap (uncurry (+) . listToTuple . fmap read) getArgs) >>= print
  where
  listToTuple [a, b] = (a, b)