Да, GHCi принимает любые значения. Вы можете сказать:
ghci> 4
4
ghci> print 4
4
Но эти два значения (4
и print 4
) явно не равны. Волшебство GHC заключается в том, что если то, что вы ввели, оценивается как IO something
, то оно выполняет это действие (и печатает результат, если something
не ()
). Если это не так, то он вызывает show
для значения и печатает это. В любом случае, эта магия недоступна из вашей программы.
Когда вы говорите:
do foo <- bar :: IO Int
baz
baz
ожидается типа IO something
, в противном случае это ошибка типа. Это позволит вам выполнить ввод-вывод, а затем вернуть чистое значение. Вы можете проверить это, заметив, что отладка вышеприведенного приводит к:
bar >>= (\foo -> baz)
И
-- (specializing to IO for simplicity)
(>>=) :: IO a -> (a -> IO b) -> IO b
Поэтому
bar :: IO a
foo :: a
baz :: IO b
Способ исправить это - преобразовать возвращаемое значение в значение IO с помощью функции return
:
return :: a -> IO a -- (again specialized to IO)
Тогда ваш код:
titleFromUrl url = do
(_, page) <- curlGetString url [CurlTimeout 60]
return $ matchRegex (mkRegexWithOpts "<title>(.*?)</title>" False True) page
Для большей части приведенного выше обсуждения вы можете заменить любую монаду на IO
(например, Maybe
, []
, ...), и она все равно будет верной.