Haskell: список понимания записей Glade - PullRequest
0 голосов
/ 06 августа 2011

Я хочу сделать entries :: Map(String -> Entry), чтобы я мог легко получить доступ к каждой записи по имени.Для этого у меня есть код

  Just xml ←  xmlNew "blah.glade"
  ...
  entries ← fromList $ [(name,entry) | name <- entryList 
      , entry <- xmlGetWidget xml castToEntry name]

(где entryList - это список имен записей, например, ["name1","name2",...]).

Однако понимание списка приходит сследующая ошибка:

   Couldn't match expected type `[t]' against inferred type `IO Entry'
    In the expression: xmlGetWidget xml castToEntry name
    In a stmt of a list comprehension:
        entry <- xmlGetWidget xml castToEntry name
    In the second argument of `($)', namely
        `[(name, entry) |
              name <- entryList, entry <- xmlGetWidget xml castToEntry name]'

Я не могу понять, почему он ожидает список чего-либо.Кто-нибудь может помочь с этим?

1 Ответ

2 голосов
/ 06 августа 2011

Это потому, что <- в понимании списка ожидает, что правая часть будет списком. Вы пытаетесь использовать его для привязки результата действия IO, но это допустимо только в записи do (по крайней мере, без расширений).

Проблема в том, что xmlGetWidget возвращает IO Entry, но вам нужна карта Entry. Это означает, что вам придется скомпоновать эти IO действий в большее.

В конце концов, вы захотите что-то вроде этого:

let getEntry name = do entry <- xmlGetWidget xml castToEntry name
                       return (name, entry)
entries <- fromList <$> mapM getEntry entryList

Здесь я создал вспомогательную функцию getEntry :: String -> IO (String, Entry), чтобы получить запись и связать ее с ее именем.

Далее я использую mapM для сопоставления getEntry со списком имен. Обратите внимание на разницу между map и mapM. Если бы я использовал map, я бы получил список действий, то есть [IO (String, Entry)], когда мне нужно действие, возвращающее список, т.е. IO [(String, Entry)].

Теперь, построив это действие IO, я преобразую его в Map, используя fromList с оператором <$>. Также известный как fmap, <$> применяет чистую функцию к объекту внутри IO, поэтому результат имеет тип IO (Map String Entry).

Наконец, результат этого действия IO можно связать с entries.

...