Как GHCi выбирает экземпляр класса типа Monad для использования в полиморфных действиях?
Я новичок в Хаскелле, так что это может быть нубовский вопрос.
Когда я делаю return 10 >>= return
GHCi показывает 10
. Когда я проверяю тип return 10
с :t
, он просто говорит return 10 :: (Monad m, Num a) => m a
, и я делаю typeOf return 10
, я получаю ошибку.
>>=
для оценки return 10 >>= return
, так какой экземпляр он использовал и как он решил, какой из них использовать?1 ответ:
Это следует из идеи, что GHCi является чем-то вроде гигантского блока
do
IO
. Всякий раз, когда вы вводите что-то, что является выражением, он сначала пытается увидеть, может ли тип результата быть специализирован на чем-то в формеIO a
. Если это возможно, он выполняет действиеIO
и просто печатает результат. Только в противном случае он выводит результат самого выражения.Чтобы заставить GHCi перейти к любой конкретной монаде, которую вы хотите, вы можете добавить аннотацию типа. Обратите внимание, как
IO
получает трактуется по-разному (и так же, как трактовалось бы выражение без всякой аннотации).ghci> return 10 >>= return :: Maybe Int Just 10 ghci> return 10 >>= return :: [Int] [10] ghci> return 10 >>= return :: IO Int 10
В стороне, есть совершенно другая проблема относительно того, какой экземпляр
Num
выбран, и это имеет все отношение к нарушению правил и ограничению мономорфизма.