2016-02-02 12 views
8

W Pipes Tutorial, to mówi, że:Dlaczego Haskell Pipes "używać() do zamknięcia nieużywanych wejść i X (niezamieszkanego typu), aby zamknąć nieużywane wyjścia"?

Konkretne synonimami typu użyć () zamknąć nieużywane wejścia i X ( wpisać niezamieszkana), aby zamknąć nieużywane wyjścia:

Chciałbym zrozumieć, dlaczego () i X są używane tak, jak są. Dlaczego nie X lub () dla wejść i wyjść?

+0

Może warto przyjrzeć się temu pytaniu, a także znakomitym odpowiedziom: ["Do czego służy funkcja' absurdu' w "Data.Void"?] (Http://stackoverflow.com/questions/14131856/ whats-the-absurdalna-funkcja-w-danych-void-użytecznych-for) –

Odpowiedz

6

X w rurach jest zwykle napisane w innym ekosystemie Void, udawajmy więc X = Void. Jest zdefiniowany następująco:

data Void 

I to ma „eliminator”

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

Jeśli masz coś typu Void (i zmusić go), a następnie coś poszło nie tak. Twój program spowodował błąd lub utknął w nieskończonej pętli.

Wykonywanie rury produkuje rzeczy typu Void umieszcza ją w dowolnym momencie (uzasadnione). Sprawiając, że produkuje on przedmioty typu (), pozwala produkować rzeczy, ale rzeczy, które nie niosą żadnych informacji. Zasadniczo są to tykanie zegara.

Po stronie wejściowej, rura, która zużywa przedmioty typu Void może czekać na dane wejściowe, ale tak szybko, jak to zrobi, utknie - nikt nie będzie mógł go podać. Rura, która zużywa przedmioty typu () może czekać, ale dostaje tylko tyknięcia zegara.

Wszystkie te opcje są uzasadnione. Podejrzewam, że Gonzalez chciał, aby system typu zabraniał użytkownikom przypadkowego podłączenia czystego producenta do czystego konsumenta w niewłaściwy sposób i uzyskania błędu, który może być trudny do wyśledzenia. Poprzez zrobienie czystego producenta konsumuje się (), a czysty konsument produkuje Void, uniemożliwia to podłączenie go w niewłaściwy sposób.

+0

'Pipes.X' jest bardziej jak' Void' pakietu 'void',' newtype X = XX', z 'closed (X x) = closed x' dla 'absurdu', ale punkt jest w zasadzie taki sam. – Michael

+0

@Michael, to pewnie dlatego, że jest to ewolucyjna pozostałość, której może być zbyt trudno się pozbyć. Pakiet 'Void' faktycznie kompiluje tylko ten kod dla starych wersji' base' - w przeciwnym razie większość pakietu jest wypatroszona przez Cabala na rzecz wersji 'base'. – dfeuer

+0

Dobra, to był mój punkt widzenia. – Michael

3

W rzeczywistości jest to coś więcej niż tylko rury. () i Xinitial and terminal objects z HASK kategorii (i kategorii pochodzącego z HASK), co oznacza, że ​​dla wszystkich typów Haskell a,

  • istnieje dokładnie jeden morfizm a ->() (mianowicie const())
  • istnieje dokładnie jeden morfizm X -> a (a mianowicie absurd).

W konsekwencji, każdy łańcuch funkcji a ->() >>>() -> b nie może faktycznie zależą od lewej strony (od a ->() niesie żadnej informacji), a każdy łańcuch a -> X >>>X -> b nie może zależeć od prawa część.W tym sensie wejście () -> b jest zamknięte, podobnie jak wyjście a -> X.

+2

Ale rury nie są funkcjami. Rura może konsumować bez wytwarzania, produkować bez konsumowania, a nawet siedzieć bez skutku. Nie sądzę, że kategoria rur nad monadą nie identyfikującą może w ogóle mieć początkowe lub końcowe obiekty. – dfeuer

+0

Dla dowolnych dwóch typów 'a' i' b', będą "więcej" potoków, które zużywają 'a' i produkują' b' niż funkcje 'a -> b'. – dfeuer

Powiązane problemy