2016-02-02 1 views
8

В Pipes Tutorial, он говорит, что:Почему Haskell Pipes «использует() для закрытия неиспользуемых входов и X (нежилой тип) для закрытия неиспользуемых выходов»?

Синонимы конкретного типа использует () закрыть неиспользуемые входы и X ( необитаемого типа), чтобы закрыть неиспользуемые выходы:

Я хотел бы понять, почему () и X используются так, как они есть. Почему не X или () для обоих входов и выходов?

+0

Возможно, вы захотите посмотреть на этот вопрос, а также на отличные ответы: «Что такое функция« absurd »в« Data.Void »?» (Http://stackoverflow.com/questions/14131856/ Whats-the-absurd-function-in-data-void-useful-for) –

ответ

6

X в трубах обычно пишется Void в остальной экосистеме Haskell, поэтому давайте притворимся X = Void. Он определяется следующим образом:

data Void 

И это имеет «выпрямитель»

absurd :: Void -> a 
absurd x = case x of {} 

Если у вас есть что-то типа Void (и заставить его), то что-то пошло не так. Ваша программа вызвала ошибку или застряла в бесконечном цикле.

Изготовление трубы Изделие вещи типа Void запрещает это когда-либо производить что-либо (законное). Изготовление этого продукта типа () позволяет ему создавать вещи, но вещи, которые не содержат никакой информации. Они в основном часы.

На входной стороне трубка, которая потребляет вещи типа Void, может ждать ввода, но как только она это сделает, она застряла - никто не сможет ее накормить. Труба, которая потребляет вещи типа (), может ждать, но только получает тики часов.

Все эти варианты являются разумными. Я подозреваю, что Гонсалес хотел, чтобы система типов запрещала пользователям случайно подключать чистого производителя к чистому потребителю неправильно, и получить ошибку, которую трудно отследить. Чистый производитель потребляет (), а чистый потребительский продукт Void, он делает невозможным их неправильное подключение.

+0

'Pipes.X' больше похож на' Void' пакета 'void',' newtype X = XX', с 'closed (X x) = замкнутый x' для 'absurd', но точка в основном такая же. – Michael

+0

@ Майкл, это, вероятно, потому, что это эволюционный остаток, от которого может быть слишком сложно избавиться. Пакет 'Void' фактически компилирует этот код для старых версий' base' - в противном случае большая часть пакета портится Cabal в пользу «базовых» версий. – dfeuer

+0

Правильно, это была моя точка. – Michael

3

Это на самом деле более общая вещь, чем для труб. () и X являются initial and terminal objects из HASK категории (и категорий, полученных от HASK), а это означает, что для всех типов Haskell a,

  • существует ровно один морфизм a ->() (а именно const())
  • существует ровно один морфизм X -> a (а именно absurd).

Как следствие, любая цепочка функций a ->() >>>() -> b фактически не может зависеть от левой части (поскольку a ->() не несет никакой информации), а также любая цепь a -> X >>>X -> b не может зависеть от правый часть.В этом смысле вход () -> b закрыт, а также выход a -> X.

+2

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

+0

Для любых двух типов 'a' и' b' будет существовать «больше» труб, которые потребляют 'a' и производят' b', чем функции 'a -> b'. – dfeuer

Смежные вопросы