Это верно - Haskell может отправлять по типу возврата. Фактически, поскольку Haskell является функциональным языком, не существует строгого понятия «возвращаемый тип». Например, Int
в (Bool -> Int) -> String
тип возврата?
Итак, как это происходит? Во-первых, Haskell определяет тип выражения. Имеет форму
forall x1 x2 [...] . Ctx => t
где Ctx
является контекстом и имеет вид (Class1 vars1, Class2 vars2, ...)
.
Теперь в большинстве случаев (как и у вас) все переменные типа, встречающиеся в контексте, также встречаются в типе t
. Следовательно, как только эти переменные будут созданы для конкретных типов, можно разрешить перегруженные методы.
В частности, в вашем случае Haskell знает, что оператор связывания >>=
имеет тип
m a -> (a -> m b) -> m b.
Поскольку правый операнд имеет тип Parser b
для некоторых b
, переменная m
должна быть Parser
, поэтому return
имеет тип a -> Parser a
.
В некоторых случаях в контексте могут быть переменные, которые не встречаются в t
.
Е.Г.
show (read "blah")
имеет тип String
, но для оценки необходимо выбрать несколько экземпляров классов Read
и Show
.
В этом случае оно либо разрешается с использованием механизма по умолчанию *1038*, либо сообщается об ошибке. В последнем случае вы можете исправить это, указав явную подпись.