В принципе, если вы не используете forall
, все типы являются глобальными в определении функции, что означает, что все они выведены при вызове функции. С forall
вы можете отказаться от того, что для функции, принимающей x
, пока она не назовет себя.
Так в первом у вас есть функция, которая принимает x
и дает c x
, то у вас есть кортеж с a
и b
, и вы ожидаете кортеж с c a
и c b
. Поскольку вы уже сказали, что первая функция принимает x
, вы можете сделать x
таким же, как a
, но это не будет b
, потому что x
определяется один раз для всей декларации. Таким образом, вы не можете заставить функцию принимать как a
, так и b
.
Однако во втором случае область действия x
ограничена функцией, принимающей x
. Мы в основном говорим, что есть функция, которая берет что-то и делает c
с чем-то, и это может быть любой тип. Это позволяет нам сначала подать a
, а затем b
, и он будет работать. x
не должно быть чем-то особенным сейчас снаружи.
Что вы видите в определении Monad
- это расширение языка «Явное право». Существует описание на Haskell Prime для этого расширения
ExplicitForAll позволяет использовать ключевое слово «FORALL», чтобы явно указать, что тип является полиморфным в своем свободном переменном типе. Он не позволяет записывать какие-либо типы, которые уже не могут быть записаны; он просто позволяет программисту явно указать (в настоящее время неявное) количественное определение.
Это языковое расширение является чисто визуальным, позволяет выписывать переменные явно, которые вы ранее не могли. Вы можете просто опустить forall a b.
из объявления Monad
, и программа будет функционировать точно так же.
Скажите, с помощью этого расширения вы можете переписать liftTupe
как forall a b x. (x -> c x) -> (a, b) -> (c a, c b)
. Определение одно и то же, и оно функционирует одинаково, но теперь читатели ясно видят, что все переменные типа определены на самом верхнем уровне.
Не знаю, почему все ответы так многословны. В одном предложении: вы правы; он ничего не меняет и просто должен быть явным. – Ryan
'forall a b. <..> 'в типе' >> = '* * привязан к определенной функции - функция' m a -> (a -> m b) -> m b'. Вы также можете иметь 'forall' без функции, например. '[] :: forall a. [a] ',' empty :: forall f a. Альтернатива f => f a'. – user2407038
@ Ryan Когда я получаю ответ: «Потому что все неявно квалифицировано». мой последующий вопрос часто «Почему?». – ThreeFx