Haskell Snap: выполнение действия ввода-вывода в обработчике? - PullRequest
2 голосов
/ 25 марта 2012

Скажем, у меня есть случайная функция DB в моем отдельном файле DB.hs. Примерно так:

savePerson :: Person -> IO ()
  savePerson p = do
  c <- connect
  run c "INSERT INTO persons (name, age) \
        \VALUES (?, ?)"
        [toSql (personName p), toSql (personAge p)]
  commit c
  disconnect c
  return ()

Теперь, как мне выполнить эти функции в моем обработчике в Site.hs, если я импортирую свой DB.hs?

Если я просто воткну его в свой обработчик вот так (это всего лишь пример):

insertPerson = do
  par <- getPostParams
  let p = toPerson par
  savePerson p
  return ()
  where
    toPerson m =
      Person {personName = head (m ! (B.pack "name"))
             ,personAge  = read (B.unpack (head (m ! (B.pack "age")))) :: Int
             }

Это не работает. Я не хочу, чтобы обработчик возвращал что-либо, я просто хочу, чтобы он сохранил Персона и ничего не возвращал / не рендерил.

Как правильно это сделать?

Спасибо.

1 Ответ

1 голос
/ 25 марта 2012

Похоже, ваша проблема в том, что вы не понимаете, что такое тип и значение единицы измерения.

Тип модуля - это специальный встроенный тип, называемый «()», который имеет ровно одно значение, также называемое «()».

Так, например, я могу создать список из 4 единиц, который имеет тип "список единиц".

fourUnits :: [()]
fourUnits = [(), (), (), ()]

Тип единицы измерения используется там, где мы не хотим иметь никакой другой информации. Технически, тип «IO ()» - это тип действия IO, которое дает значение единицы.

Предложение "do" unsugars в цепочке вызовов ">> =". ">> =" имеет тип

(>>=) :: (Monad m) => m a -> (a -> m b) -> m b

Другими словами, тип предложения "do" - это тип, возвращаемый его последним действием.

Так, где вы говорите

savePerson p
return ()

«return ()» является ложным, потому что имеет тот же тип, что и «savePerson p».

Помните, что return не имеет ничего общего с потоком управления: это просто функция с типом

return :: (Monad m) => a -> m a

Во избежание этой путаницы было бы лучше назвать «обернуть» или «впрыснуть» или что-то подобное

...