Lemat: Zakładając, że równoważność eta istnieje (\x -> ⊥) = ⊥ :: A -> B
.
Dowód: ⊥ = (\x -> ⊥ x)
przez eta-równoważność i (\x -> ⊥ x) = (\x -> ⊥)
redukcję pod lambda.
Raport Haskell 2010, rozdział 6.2 określa seq
funkcję na podstawie dwóch równań:
seq :: a -> b -> b seq ⊥ b = ⊥ seq ab = b, jeśli a ≠ ⊥
Następnie twierdzi, że „W konsekwencji not nie jest tym samym, co \ x -> ⊥, ponieważ można je rozróżnić za pomocą seq.”
Moje pytanie brzmi, czy to naprawdę konsekwencja definicji seq
?
Domniemany argument wydaje się być taki, seq
że gdyby nie seq (\x -> ⊥) b = ⊥
. Jednak nie byłem w stanie udowodnić, że takie seq
byłoby niemożliwe do obliczenia. Wydaje mi się, że taki seq
jest zarówno monotoniczny, jak i ciągły, co stawia go w sferze obliczalności.
Algorytm że wdrożenie takich jak praca nast może próbując szukać dla niektórych x
gdzie f x ≠ ⊥
przez wyliczanie domenę f
zaczynając ⊥. Chociaż taka implementacja, nawet jeśli jest to w ogóle możliwe, staje się dość owłosiona, gdy chcemy stworzyć seq
polimorfię.
Czy istnieje dowód, że nie ma obliczalnego seq
identyfikującego się (\x -> ⊥)
z ⊥ :: A -> B
? Alternatywnie, jest tam jakiś budowa seq
które nie identyfikują (\x -> ⊥)
się z ⊥ :: A -> B
?
źródło
seq
seq
Zauważ, że specyfikacja, dla
seq
której zacytujesz, nie jest jej definicją. Cytując raport Haskella „Sekwencja funkcji jest zdefiniowana przez równania : [a następnie podane równania]”.Takie zachowanie naruszałoby specyfikację
seq
.Co ważne, ponieważ
seq
jest polimorficzny,seq
nie można go zdefiniować w kategoriach dekonstruktorów (dopasowanie rzutów / wzorców itp.) Dla żadnego z dwóch parametrów.Jeśli
seq' (\x -> ⊥) b
można by pomyśleć, że moglibyśmy zastosować pierwszy parametr (który jest funkcją) do pewnej wartości, a następnie uzyskać ⊥. Aleseq
nigdy nie można zidentyfikować pierwszego parametru z wartością funkcji (nawet jeśli zdarza się, że jest to jeden do użytkuseq
) ze względu na jego parametryczny typ polimorficzny. Parametryzacja oznacza, że nic nie wiemy o parametrach. Co więcej,seq
nigdy nie można wyrazić i zdecydować „czy to jest?”. (por. problem Haltinga),seq
może jedynie próbować go ocenić i sam się rozbiega na ⊥.Co
seq
nie jest ocena pierwszy parametr (nie całkowicie, ale do „słabych główki normalnej postaci” [1], to znaczy do górnej skrajnej konstruktora), a następnie powrócić do drugiego parametru. Jeśli zdarzy się, że pierwszym parametrem jest⊥
(tj. Obliczenie nie kończące się), wówczas jego ocena powoduje,seq
że nie jest on zakończony, a zatemseq ⊥ a = ⊥
.[1] Bezpłatne twierdzenia w obecności seq - Johann, Voigtlander http://www.iai.uni-bonn.de/~jv/p76-voigtlaender.pdf
źródło
f : forall a . a -> T
(gdzieT
jest jakiś inny typ), wówczasf
nie może zastosować żadnych dekonstruktorów do swojego pierwszego argumentu, ponieważ nie wie, które dekonstruktory mają zostać zastosowane. Nie możemy zrobić „przypadku” dla typów. Próbowałem poprawić powyższą odpowiedź (w tym powołując się na informacje dotycząceseq
oceny do normalnej formy głowy).Samson Abramsky rozważał tę kwestię dawno temu i napisał artykuł zatytułowany „ The Lazy Lambda Calculus ”. Tak więc, jeśli chcesz formalne definicje, tutaj możesz poszukać.
źródło
Udowadniając, że λ x. Ω ≠ Ω jest jednym z celów wyznaczonych przez Abramsky'ego dla jego leniwej teorii rachunku lambda (strona 2 jego pracy , cytowanej już przez Udaya Reddy'ego), ponieważ oba są w normalnej formie słabej głowy. Od definicji 2.7 wyraźnie dyskutuje, że eta-redukcja λ x. M x → M nie jest ogólnie poprawny, ale jest możliwe, jeśli M kończy się w każdym środowisku. Nie oznacza to, że M musi być funkcją całkowitą - tylko to, że ocena M musi się zakończyć (na przykład poprzez redukcję do lambda).
Twoje pytanie wydaje się być motywowane względami praktycznymi (wydajność). Jednak, mimo że Raport Haskella może być mniej niż całkowicie jasny, wątpię, by zrównanie λ x. Ith „z” stworzyłoby przydatną implementację Haskella; kwestia, czy implementuje Haskell '98, czy nie, jest dyskusyjna, ale biorąc pod uwagę uwagę, jasne jest, że autorzy zamierzali, aby tak było.
Wreszcie, w jaki sposób seq generuje elementy dla dowolnego typu danych wejściowych? (Wiem, że QuickCheck definiuje w tym celu typ Arbitrary, ale nie możesz tutaj dodawać takich ograniczeń). Narusza to parametryczność.
Zaktualizowano : Nie udało mi się zakodować tego poprawnie (ponieważ nie jestem tak biegły w Haskel), a naprawienie tego wymaga zagnieżdżonych
runST
regionów. Próbowałem użyć pojedynczej komórki referencyjnej (w monadzie ST), aby zapisać takie dowolne elementy, przeczytać je później i uczynić je powszechnie dostępnymi. Parametryzacja dowodzi, żebreak_parametricity
poniżej nie można zdefiniować poniżej (z wyjątkiem zwracania wartości dolnej, np. Błędu), podczas gdy może odzyskać elementy, które wygenerowałaby proponowana sekwencja.Muszę przyznać, że jestem nieco rozmyślny nad sformalizowaniem wymaganego tutaj dowodu parametrycznego, ale to nieformalne użycie parametryczności jest standardowe w Haskell; ale dowiedziałem się z pism Dereka Dreyera, że potrzebna teoria jest szybko opracowywana w ostatnich latach.
EDYCJE:
źródło
(\x -> writeSTRef cell (Just x) >> return x)
losowych danych wejściowych nie powoduje zapisu do komórki.runST
Zawsze wykonywane są tylko polecenia ST, które przechodzą do sekwencyjnie przekazanego polecenia . Podobnie działaniemain = (putStrLn "Hello") `seq` (return ())
nie drukuje niczego na wyświetlaczu.