Haskell: Как читать в командной строке args как int?

Я пытаюсь получить значение int из командной строки и передать его функции disp.

import System(getArgs)

main = do
    args <- getArgs
    disp $ read $ head args :: Int

disp n = take n $ repeat 'S'

Ошибка, заданная ghc, равна

 Couldn't match expected type `Int' with actual type `[Char]'
 In the expression: disp $ read $ head args :: Int
 In the expression:
   do { args <- getArgs;
            disp $ read $ head args :: Int }
 In an equation for `main':
     main
       = do { args <- getArgs;
                  disp $ read $ head args :: Int }

Спасибо.

Ответ 1

Проблема заключается в precendence: сигнатуры типов всегда пытаются применить к всему выражению (только в скобках с использованием скобок). Таким образом, ваш disp $ read $ head args :: Int анализирует как (disp $ read $ head args) :: Int, что, очевидно, неверно. Вы можете использовать скобки так:

disp (read $ head args :: Int)

или опустить подпись типа, поскольку GHC может вывести его в этом случае:

disp $ read $ head args

Этот код по-прежнему не работает как есть, потому что вы находитесь в монаде IO, поэтому вам нужно произвести действия IO. Вы можете сделать это, распечатав результат, например:

putStrLn $ disp $ read $ head args

Ответ 2

Вы можете инкапсулировать вытягивание целочисленного аргумента командной строки следующим образом:

getIntArg :: IO Int
getIntArg = fmap (read . head) getArgs

Что работает, потому что Monads - это функторы. Или вы можете сделать то же самое с liftM.

Таким образом ваша функция main просто станет:

main = do
    n <- getIntArg
    disp n

Если вы добавите какой-либо тип функции печати в disp, как описано в других ответах.

Ответ 3

Просто удалите этот явный тип, который вы там добавили, и он будет работать. Имейте веру в вывод типа.:) Добавьте print $ ... там или что-то подобное, чтобы исправить новую ошибку.

Что происходит, тип take известен, поэтому также известен тип аргумента, который ожидает disp. Это Int. Таким образом, будет применен соответствующий read.

Сделайте меньше, сделайте больше.