Haskell Рекурсивная функция по списку ввода-вывода - PullRequest
0 голосов
/ 18 октября 2011

У меня есть следующая функция, которая перебирает список [(Map String SqlValue)]

extractPatternStrings ∷ IO [(Map String SqlValue)] → IO [String] 
extractPatternStrings [] = do
    return []
extractPatternStrings lst = do
    (m:ms) ←  lst
    return $ (toString m) : (extractPatternStrings ms)
    where
        toString ∷  Map String SqlValue → String 
        toString m = (fromSql . fromJust . (Map.lookup "word"))∷ String

За исключением случая, когда пустой список говорит мне, что он не может соответствовать ожидаемому IO [Map String SqlValue] фактическому [t0].

Я думал, что do = return позаботится об этом.Как мне исправить это?

Редактировать: Чтобы ответить, почему я использую IO:

Функция вызывается из selectAll ↠ extractPatternStrings, где selectAll читает из базы данных.

Ответы [ 2 ]

7 голосов
/ 18 октября 2011
extractPatternStrings ∷ IO [(Map String SqlValue)] → IO [String]

IO [String] - это действие ввода-вывода, которое дает результат [String].Использование нотации do гарантирует, что extractPatternStrings создаст IO [String], а не [String].

. IO [(Map String SqlValue)] - это действие ввода-вывода, которое приводит к результату [Map String SqlValue].Но вы не можете сопоставить шаблон с действием ввода-вывода.Синтаксис, который вы используете, предназначен для прямого сопоставления со списком, а не с действием ввода-вывода, которое создает список.

Вместо этого следует использовать подпись этого типа:

extractPatternStrings ∷ [Map String SqlValue] → IO [String] 

За исключением этого, как @Пропущенный не указывает, что это не должно быть действие ввода-вывода:

extractPatternStrings ∷ [Map String SqlValue] → [String] 
extractPatternStrings []     = []
extractPatternStrings (m:ms) = toString m : extractPatternStrings ms
    where
        toString ∷  Map String SqlValue → String 
        toString m = (fromSql . fromJust . (Map.lookup "word"))∷ String

Или, что лучше (и исправление ошибки в toString):

extractPatternStrings ∷ [Map String SqlValue] → [String] 
extractPatternStrings = map toString
    where
        toString ∷  Map String SqlValue → String 
        toString = fromSql . fromJust . Map.lookup "word"

Более кратко:

extractPatternStrings ∷ [Map String SqlValue] → [String] 
extractPatternStrings = map (fromSql . fromJust . Map.lookup "word")

Если вы действительно должны иметь оригинальную подпись, то используйте liftM, либо изменив свой код вызова на selectAll ↠ liftM extractPatternStrings (и я должен признаться, я не узнаю оператора, которого вы там используете)или определив extractPatternStrings как

extractPatternStrings ∷ IO [Map String SqlValue] → IO [String] 
extractPatternStrings = liftM $ map (fromSql . fromJust . Map.lookup "word")

Но я рекомендую первое.

2 голосов
/ 18 октября 2011

return упаковывает возвращаемое значение в IO, поэтому он заботится о типе возврата IO [String].Однако это не поможет вам с типом аргумента, который равен [(Map String SqlValue)], но который вы пытаетесь сопоставить с пустым списком.По сути, вы не можете сопоставить шаблон со значениями ввода-вывода.

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

extractPatternStrings lstIO = do
  lst <- lstIO
  case lst of
    [] -> ...
    (m:ms) -> ...
...