Это потому, что <-
в понимании списка ожидает, что правая часть будет списком. Вы пытаетесь использовать его для привязки результата действия 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
.