Каково предположение, сделанное в «Learn You a Haskell» при выводе вида?

18

Этот вопрос не субъективен. В упомянутой книге используется очень специфический глагол, и я хотел бы понять, каково значение этой фразы, потому что, боюсь, я что-то неправильно понимаю.

Из « Learn You a Haskell» следующий абзац третий и последний содержит «мы предполагаем *».

data Barry t k p = Barry { yabba :: p, dabba :: t k }  

И теперь мы хотим сделать это примером Functor. Functorхочет типа, * -> *но Barryне выглядит так, как у него Что это за вид Barry? Ну, мы видим, что он принимает три параметра типа, так что будет something -> something -> something -> *. Можно с уверенностью сказать, что pэто конкретный тип и, следовательно, имеет своего рода *. Ибо k, как мы предполагаем, *и так по расширению, tимеет вид* -> * . Теперь давайте просто заменим эти типы на somethings, которые мы использовали в качестве заполнителей, и мы увидим, что они имеют вид (* -> *) -> * -> * -> *.

Почему мы вообще что-то предполагаем? После прочтения «мы предполагаем, что X (то есть мы предполагаем, что X истинно)», для меня естественно думать, что мы должны также рассмотреть случай, когда X ложно. В конкретном случае примера не может tбыть добрым (* -> *) -> *и kдобрым (* -> *)? Если бы это было так, то все , что tи на kсамом деле были, по- t kпрежнему будет тип бетона, нет?

Я вижу, что вся цепочка рассуждений затем проверяется с помощью компилятора, но я не думаю, что компилятор предполагает . Если это произойдет, я хотел бы знать, что, если это не так, то, опять же, я боюсь, что мне не хватает значения параграфа.

Энрико Мария Де Анжелис
источник
4
Ты прав. Действительно, мы можем иметь k :: Lдля любого вида L, пока t :: L -> *. Компилятор здесь, однако, должен выбрать какой-то конкретный Lтип или прибегнуть к поликинду. Поликинд был бы наиболее общим вариантом, но здесь GHC выбирает L = *(базовый Haskell не имеет поликиндов, они должны быть включены как расширение). Поскольку он выбирает что-то довольно произвольное, LYAH использует слово «предположить» (AFAICT).
Чи
1
Хорошо, может быть, компилятор предполагает, что озадачил меня, по крайней мере, меньше, чем мы предполагаем , или нет вообще.
Энрико Мария Де Анжелис

Ответы:

19

На самом деле, компилятор предполагает! Но вы можете попросить об этом не с расширением PolyKinds. Подробнее об этом можно прочитать здесь . С этим расширением вид Barryбудет forall k. (k -> *) -> k -> * -> *.

Даниэль Вагнер
источник
-1

Хорошая точка зрения. Автор делает ненужное предположение. Возможно, просто для того, чтобы облегчить понимание в его главе Type Foo, но такие люди, как вы, могут справедливо усомниться в этом.

Оба t, kи pявляются переменными типа. Как мы видим из этого, yabba :: pон может жить один, поэтому он похож на константу, как если бы это было значение вместо типа, его сигнатура типа сказала бы Intили Char, как угодно ... вы называете это. Но так как это тип, то это и есть подпись *.

Однако tтип здесь принимает переменную типа kдля создания type ( dabba :: t k), поэтому мы уверены, что (здесь нет предположений) tимеет такую ​​же сигнатуру типа, как * -> *и kимеет* .

Как только мы узнаем это ... типовая Barry t k pсигнатура типа (* -> *) -> * -> * -> *означает, что она принимает tто kи другое pи дает нам Barryтип.

Редактировать Не забудьте прочитать комментарий @ luqui ниже.

Redu
источник
7
kне обязан быть таким, *каким вы утверждаете, что это при выводе t. Мы могли бы k :: * -> *и t :: (* -> *) -> *, например. Добавьте поле doo :: k Intк записи, и оно пройдет без проблем.
Луки
@luqui .. Да, вы правы ... Я не буду удалять этот ответ, так как ваш комментарий действительно стоит того.
Redu