Я бы хотел написать такую ​​программу:

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

Есть ли способ записать функцию getIntArgs в терминах getArgs (из System.Environment)?

2
Cameron Ball 11 Сен 2018 в 06:54

1 ответ

Лучший ответ

Сначала разверните его в голове. Вам нужна функция, которая идет от 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)
2
Adam Smith 11 Сен 2018 в 04:44