Тип функции Haskell с IO - PullRequest
       1

Тип функции Haskell с IO

0 голосов
/ 28 апреля 2011

Я путаю с некоторыми вещами в haskell. Сначала я четко объясню свою проблему,

У меня есть вызов функции "func1", который получает результат из БД

определение типа func1 :: IO[[String]]

func1 = do
 xx <- main --returns the sql output
 return (map (map fromSql) xx :: [[String]])

Мне нужно написать две функции, которые дают мне funcWnt :: IO[[String]] -> [[String]] и funcWnt2 :: [String] -> Splice m

Я пытался <- в «funcWnt», но это не удалось. Кто-нибудь может сказать мне, как это сделать? хочу узнать функцию 'funcWnt'

thnxxxx !!

1 Ответ

2 голосов
/ 08 мая 2011

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

Давайте посмотрим, сможем ли мы взять то, что вы думаете об этом, и переформулировать это по-новому:

У вас есть:

readDB :: IO [[SqlValue]]
readDB = ... -- not given here

func1 :: IO [[String]]
func1 = do
  xx <- readDB
  return (map (map fromSql) xx)

Теперь вы хотите написать что-то, что преобразует это. Один из способов - просто скопировать шаблон, который вы уже использовали:

funcWnt :: IO [[String]]
  yy <- func1
  return ... -- some transformation of yy

funcWnt2 :: IO (Splice m)
  zz <- funcWnt
  return ... -- some transformation of zz into a Splice m

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

func1 :: [[SqlValue]] -> [[String]]
func1 = map (map fromSql)

funcWnt :: [[String]] -> [[String]]
funcWnt = ... -- some transformation

funcWnt2 :: [[String]] -> Splice m
funcWnt2 = ... -- some transformation into a Splice m

Теперь вы можете легко комбинировать их и использовать в одном IO значении:

dbToSplice :: IO (Splice m)
dbToSplice = do
  xx <- readDB
  return $ (funcWnt2 . funcWnt . func1) xx

Или, может быть, более идиоматически (не бойтесь >>=, выучите это рано):

dbToSplice :: IO (Splice m)
dbToSplice = readDB >>= return . funcWnt2 . funcWnt . func1

Теперь, если ради аргумента, funcWnt2 нужно что-то сделать в IO. Тогда определения будут выглядеть так:

funcWnt2 :: [[String]] -> IO (Splice m)
funcWnt2 zz = do
  ... -- compute something with zz
  return ... -- returning some Splice m

dbToSplice :: IO (Splice m)
dbToSplice = readDB >>= funcWnt2 . funcWnt . func1

Наконец, обратите внимание, что я помещаю сигнатуры типов в каждую функцию верхнего уровня. Вы должны привыкнуть делать это тоже. Он не только помогает прояснить ваши намерения (для вас самих, других разработчиков или даже для себя через неделю), но также устраняет множество неуклюжих аннотаций типа, которые вы должны были вставить в func1.

...