ошибка новичка с монадой ввода-вывода и синтаксисом записи - PullRequest
2 голосов
/ 15 ноября 2011

Вот упрощенная версия моего кода:

data Bookmark = Bookmark {
   url :: String
 , label :: String
 } deriving (Show)

genBookmark :: String -> String -> IO Bookmark
genBookmark u l = return ( Bookmark { url = u, label = l } )

Но строки (url, label) находятся в базе данных, поэтому мне приходится иметь дело с IO String.Должно быть, у меня очень простое решение, но я его не вижу (а обширный поиск в Интернете никуда меня не привел).

В основном я хочу изменить свой код на:

genBookmark :: IO String -> IO String -> IO Bookmark

Вот еще одна версия, иллюстрирующая проблему:

genBookmark2 :: String -> String -> Bookmark
genBookmark2 u = return ( Bookmark { url = u, label = newlabel } )
                   where newlabel = getLine

С ошибкой «Ожидаемый тип: String, Фактический тип: IO String».

====== EDIT =======

Вот "реальный код" с ошибкой (с решением, которое я получил из ответа):

getSkosConceptRight :: String -> IO SkosConcept
getSkosConceptRight catName = do
                      suConcepts <- getSubConcepts catName
                      concept <- getMainConcept catName 
                      return ( concept { subConcepts = suConcepts })

getSkosConceptWrong :: String -> IO SkosConcept
getSkosConceptWrong catName = return ( concept { subConcepts = suConcepts })
                        where suConcepts = getSubConcepts catName
                              concept = getMainConcept catName 

getMainConcept :: ShortUrl -> IO SkosConcept
getSubConcepts :: ShortUrl -> IO [SkosConcept]

1 Ответ

7 голосов
/ 15 ноября 2011

Вы пропустили ту часть кода, которая получает строку из БД. В любом случае вам необходимо "распаковать" String из вашего IO String.

В общем, вы должны избавиться от IO как можно раньше. Таким образом, вы действительно должны попробовать для типа String -> String -> Bookmark

Вот простой пример:

-- These will represent your 'get from the db' calls
ioUrl :: IO String
ioUrl = return "http://..."

ioLabel :: IO String
ioLabel = return "my label"

genBookmark :: String -> String -> Bookmark
genBookmark url label = Bookmark { url = url, label = label }

Теперь из main, который находится в IO, мы делаем наши вызовы "db", чтобы получить наши строки, распаковать значения и отправить в нашу genBookmark функцию.

main = do
    url <- ioUrl     -- here, we're removing the "http://..." from the IO String
    label <- ioLabel -- same here
    print (genBookmark url label)

Причина, по которой ваш genBookmark2 не работает, заключается в том, что вы пытаетесь использовать getLine, тип которого IO String, в чистой функции; следовательно сообщение об ошибке expected String, got IO String. Кроме того, тип упоминает два String s как входные данные, но вы берете только один.

...