вызов сетевого ввода-вывода из haskeline

У меня есть существующая программа, которая принимает аргументы командной строки (имя пользователя, пароль, дату), а затем использует библиотеку Network.HTTP.Conduit для отправки сообщения xml на сервер. Затем я анализирую результаты, делаю некоторую работу и использую blaze-html для записи в файл.

Все это работает как шарм; однако я решил использовать haskeline, чтобы пароль не был виден. Я могу создать программу командной строки, которая получает введенные пользователем значения и распечатывает их, но если я вызову функцию, использующую канал, она никогда не вернется.

Вот код нарушения:

main = runInputT defaultSettings loop
where 
    loop :: InputT IO ()
    loop = do
        Just username <- getInputLine "WM username: "
        Just password <- getPassword (Just '*') "WM password: "
        Just date     <- getInputLine "Date (YYYYMMDD): "

        outputStrLn "querying WM..."
        clients <- lift $ getWMClients username password
        outputStrLn "successfully retrieved client list from WM..."

        let outHeader = renderHeader date username

        reportString <- mapM  (\x -> createString x clients)  cList

        lift $ writeFile (date ++ "_report.html") (outHeader ++ concat reportString)
        outputStrLn "Done"

Функция функции getWMClients:

getWMClients :: Username -> String -> IO [Client]
getWMClients username password = do
    let f = [Size "-1", Skip "0"]
    let fs = [Select "id",
              Select "status",
              Select "last-name",
              Select "first-name",
             ]
    let query = WMQuery {transaction=SHARE,service=Query,businessObject=CONT,field=f,fields=fs}

    results <- doQuery username (Just password) Nothing (Just query)
    rows <- xmlResultsToMaps results

    let clients = map makeClient rows
    return clients

Когда я запускаю программу, она зависает на «запросе WM...». Я не думаю, что http-conduit когда-либо действительно работает. Любые подсказки о том, как заставить это работать?

Заранее спасибо, Нил


person Neil    schedule 13.06.2012    source источник


Ответы (1)


Вы утверждаете, что это работало с жестко закодированными именем пользователя, паролем, датой до haskeline. Чтобы облегчить отладку, возможно, вы не смогли поднять канал в InputT. Следующее все еще терпит неудачу? (Я не компилировал это, поэтому не стесняйтесь исправлять синтаксические ошибки...)

-- Isolate the haskeline monad to just the input part:
main = loop
where 
    loop :: IO ()
    loop = do
      (username,password,date) <- runInputT defaultSettings $ do
        Just username <- getInputLine "WM username: "
        Just password <- getPassword (Just '*') "WM password: "
        Just date     <- getInputLine "Date (YYYYMMDD): "
        return (username,password,date)

      putStrLn "querying WM..."
      clients <- getWMClients username password
      putStrLn "successfully retrieved client list from WM..."

      let outHeader = renderHeader date username

      putString <- mapM  (\x -> createString x clients)  cList

      writeFile (date ++ "_report.html") (outHeader ++ concat reportString)
      putStrLn "Done"
person Chris Kuklewicz    schedule 13.06.2012
comment
Спасибо, Крис, я думаю, проблема в том, что runInpuT имеет тип (). Когда я пытаюсь это сделать, я получаю сообщение об ошибке: Couldn't match expected type ()' с фактическим типом (t0, t1, t2)' In the first argument of return', а именно (username, password, date)' In the expression: return (username, password, date) In a stmt of a 'do' expression: Just date <- getInputLine "Date (YYYYMMDD): " - person Neil; 14.06.2012
comment
В итоге я разобрал функцию цикла отдельно и вернул IO (String, String, String), и это сработало. Спасибо за помощь Крис. - person Neil; 15.06.2012