Пользовательский анализ ListView OnClick

До введения монады IO main была функцией типа [Response] -> [Request]. A Request будет представлять собой действие ввода-вывода, например, запись в канал или файл, чтение ввода или чтение переменных среды и т. Д. А Response будет результатом такого действия. Например, если вы выполнили запрос ReadChan или ReadFile, соответствующий Response будет Str str, где str будет String, содержащим вход для чтения. При выполнении запроса AppendChan, AppendFile или WriteFile ответ будет просто Success. (Предполагая, во всех случаях, что данное действие было действительно успешным, конечно).

Таким образом, программа Haskell будет работать, создавая список значений Request и считывая соответствующие ответы из списка main. Например, программа для чтения числа от пользователя может выглядеть так (без всякой необходимости обращаться к ошибкам):

main :: [Response] -> [Request]
main responses =
  [
    AppendChan "stdout" "Please enter a Number\n",
    ReadChan "stdin",
    AppendChan "stdout" . show $ enteredNumber * 2
  ]
  where (Str input) = responses !! 1
        firstLine = head . lines $ input
        enteredNumber = read firstLine 

Как уже указывал в комментарии Стивен Тетли, детальная спецификация эта модель приведена в главе 7 1.2 Haskell Report .


Могут ли I / O выполняться без IO Monad в современном Haskell?

blockquote>

Нет. Haskell больше не поддерживает способ Response / Request делать IO напрямую, а тип main теперь IO (), поэтому вы не можете писать программу Haskell, которая не включает IO и даже если вы могли бы, у вас все равно не было бы альтернативного способа ввода / вывода.

Однако вы можете написать функцию, которая принимает основную функцию старого стиля и превращает ее в IO. Затем вы могли бы написать все, используя старый стиль, а затем использовать только IO в main, где вы просто вызываете функцию преобразования на вашей реальной основной функции. Это почти наверняка будет более громоздким, чем использование монады IO (и будет путать ад из любого современного Haskeller, читающего ваш код), поэтому я определенно не рекомендовал бы его. Однако является возможным. Такая функция преобразования может выглядеть так:

import System.IO.Unsafe

-- Since the Request and Response types no longer exist, we have to redefine
-- them here ourselves. To support more I/O operations, we'd need to expand
-- these types

data Request =
    ReadChan String
  | AppendChan String String

data Response =
    Success
  | Str String
  deriving Show

-- Execute a request using the IO monad and return the corresponding Response.
executeRequest :: Request -> IO Response
executeRequest (AppendChan "stdout" message) = do
  putStr message
  return Success
executeRequest (AppendChan chan _) =
  error ("Output channel " ++ chan ++ " not supported")
executeRequest (ReadChan "stdin") = do
  input <- getContents
  return $ Str input
executeRequest (ReadChan chan) =
  error ("Input channel " ++ chan ++ " not supported")

-- Take an old style main function and turn it into an IO action
executeOldStyleMain :: ([Response] -> [Request]) -> IO ()
executeOldStyleMain oldStyleMain = do
  -- I'm really sorry for this.
  -- I don't think it is possible to write this function without unsafePerformIO
  let responses = map (unsafePerformIO . executeRequest) . oldStyleMain $ responses
  -- Make sure that all responses are evaluated (so that the I/O actually takes
  -- place) and then return ()
  foldr seq (return ()) responses

Затем вы можете использовать эту функцию следующим образом:

-- In an old-style Haskell application to double a number, this would be the
-- main function
doubleUserInput :: [Response] -> [Request]
doubleUserInput responses =
  [
    AppendChan "stdout" "Please enter a Number\n",
    ReadChan "stdin",
    AppendChan "stdout" . show $ enteredNumber * 2
  ]
  where (Str input) = responses !! 1
        firstLine = head . lines $ input
        enteredNumber = read firstLine 

main :: IO ()
main = executeOldStyleMain doubleUserInput

0
задан SquiresSquire 21 June 2012 в 07:20
поделиться