Какой тип выбран для полиморфного выражения при печати?

Какой тип return "abc" когда напечатано в ghci?

Суть вопроса в том, что в монаде она полиморфна:

ghci> :t return "abc"
return "abc" :: (Monad m) => m [Char]

и то, что печатается, зависит от того, какая монада выбрана:

ghci> return "abc" :: Maybe String
Just "abc"

ghci> return "abc" :: [] String
["abc"]

но вот что на самом деле напечатано:

ghci> return "abc"
"abc"

2 ответа

Решение

Когда вы вводите выражение expr в GHCi происходят следующие вещи:

  • Выражение проверяется типом. Если есть ошибка, GHCi сообщает об ошибке и сдается.
  • В противном случае, скажем expr найдено, чтобы иметь тип t; GHC пытается соответствовать t против IO a,
  • Если это удается, то он выполняет что-то вроде it <- exprтогда, если a это пример Show и не ()он выполняет print it,
  • Если это не удается, и t сам по себе является примером ShowGHCi делает что-то вроде let it = expr а потом print it,
  • В противном случае это жалуется.

По сути, в GHCi вам нужен способ как выполнить действия ввода-вывода, так и получить возвращаемые значения, а также поиграться с чистыми значениями и посмотреть, что вы получите. Вот почему GHCi ведет себя так, как он делает: если кажется, что вы используете действие ввода-вывода, GHCi сделает это, и затем, если это действие имеет результат, который можно показать и интересный (т.е. не ()) затем он показывает результат для вас. Если он не может показать вам результат, то это не имеет большого значения, потому что вы, вероятно, просто хотели запустить IO-действие; если бы вы хотели получить результат, вы бы назвали его <-, С другой стороны, если вам кажется, что ваше выражение не является действием ввода-вывода, GHCi рассчитывает его и показывает вам, а если его невозможно отобразить, то GHCi не может сделать ничего полезного (на этот раз никаких побочных эффектов) так жалуется.

В этом случае, return "abc" проверки типов как IO String, а также String это пример Showтак что GHCi делает что-то вроде

it <- return "abc"
print it

что по законам монады точно так же, как просто делать

print "abc"

отсюда и результат.

У Haskell есть немного озадачивающий набор правил для определения типов выражений, включающих числа; вы можете увидеть раздел отчета о неоднозначных типах и экземплярах по умолчанию. Так что ответ на общий вопрос сложен. Но в GHCi, если вы введете выражение e, вы можете положиться на следующие правила:

  • Если выражение е можно напечатать как IO T для какого-то типа T, и если T имеет Show Например, GHCi запустит вычисление и выведет полученное значение типа T, Вот что происходит в вашем третьем примере.

  • Если выражение e * не может быть набрано в IO монада, тогда вступают в силу правила экземпляра по умолчанию, и GHCi выберет тип в соответствии с этими правилами. Если тип имеет Show Экземпляр GHCi затем распечатает show эл. Вот что происходит в первых двух примерах: Maybe String а также [String] являются чистыми ценностями с Show экземпляров.

    Если тип е не имеет Show Например, тогда GHCi будет жаловаться. Это произойдет, если вы введете выражение вроде flip take,

Другие вопросы по тегам