Jeśli powiem: let 5 = 10
, dlaczego 5 + 1
zwraca 6
zamiast 11
?O użytkowniku `let 5 = 10`
Odpowiedz
Kiedy mówisz
let 5 = 10
to nie jest redefinicja 5, to dopasowywanie wzorca, ten sam, który pojawia się, gdy mówisz
foo 5 = undefined
... foo 10 ...
Wzór po prostu nie działa, jeśli to kiedykolwiek dopasowane.
W wyrażeniach letowych mecz jest leniwy. Oznacza to, że dopasowanie jest wykonywane tylko wtedy, gdy oceniana jest zmienna związana przez niego. Dzięki temu możemy napisać takie rzeczy, jak
let foo = undefined in 10
W wyrażeniu żadna zmienna nie jest powiązana, więc wzór nigdy nie jest dopasowany.
Prawdopodobnie takie wzorce bez zmiennych nie mają sensu w wiązaniach let i powinny być wykrywane przez kompilator, ale język nie zabrania ich.
Pocieszające 'let (5, x) = (10, True) w x' dostarcza' *** Wyjątek:
To jest głupie dla wiązań let, ale nie dla wszystkich: np. 'only5 xs = [5 | 5 <- xs] 'ma sens (jeśli jesteś w porządku z listami' fail'). – user3237465
@ user3237465 tak, miałem na myśli tylko wiązanie let. Aktualizacja. –
Zasadniczo
let 5 = 10 in ...
jest równoważna
case 10 of ~5 -> ...
Zanotować ~
, który oznacza leniwy lub niepodważalny wzór. Jest to wzorzec, który pasuje do wszystkiego, a to odkłada mecz do punktu, w którym faktycznie żądana jest pewna zmienna. Nie ma żadnych zmiennych w wzorze 5
, więc nic się nie dzieje.
Ta narożna obudowa jest zupełnie bezużyteczna i prawdopodobnie kompilator powinien wysłać tutaj ostrzeżenie.
celu wyjaśnienia znaczenia lazy wzorów, za to:
case f 3 of
(x,y) -> g 10 x y
tutaj f 3
oceniano najpierw (do WHNF), odsłaniając konstruktora pary. Następnie x,y
są powiązane z (jeszcze nie ocenionymi) składnikami pary. Na koniec, oblicza się g 10
, wynik jest stosowany do x
(który może być teraz wymagany), a następnie do y
(co może spowodować, że wymagany będzie x
lub y
).
porównania
case f 3 of
~(x,y) -> g 10 x y
nie rozpocznie z oceny f 3
. Zamiast tego x
jest związany z nieocenionym fst (f 3)
i y
jest związany z nieocenionym snd (f 3)
. Zamiast tego zaczynamy od oceny g 10
. Następnie stosujemy to do x
: może to wymagać x
, wywołując ocenę f 3
. Następnie stosujemy wynik do y
, powodując podobną ocenę.Większość implementacji będzie faktycznie udostępnić wynik f 3
między x
i y
tak, że zostanie obliczona co najwyżej raz.
As @ n.m. mówi, że masz dopasowywanie do wzorca. Oto kilka przykładów.
wzorzec pasuje może uda
Prelude> let (a, 10) = (15, 10) in a
15
lub nie.
Ponieważ Haskell jest leniwy, Twój kod się powiedzie, jeśli nie użyjesz wartości wynikowej. To jest w zasadzie to, co robisz:
Prelude> let (a, 10) = (15, 15) in "Something else"
"Something else"
uwaga, że typy muszą jeszcze sprawdzić:
Prelude> let (a, 10, 999) = (15, 15) in "Something else"
<interactive>:7:20: error:
• Couldn't match expected type ‘(t, Integer, Integer)’
with actual type ‘(Integer, Integer)’
• In the expression: (15, 15)
In a pattern binding: (a, 10, 999) = (15, 15)
In the expression: let (a, 10, 999) = (15, 15) in "Something else"
• Relevant bindings include a :: t (bound at <interactive>:7:6)
" Ponieważ Haskell jest leniwy, twój kod się powiedzie, jeśli nie użyjesz wartości wynikowej "- Warto wspomnieć, że ważne jest również to, aby" pozwolić " wiązania domyślnie pasują leniwie. 'case (15, 15) z {(a, 10) ->" Coś innego "}' zawiesza się, a 'case (15, 15) z {~ (a, 10) ->" Coś innego "} (które , dzięki leniwemu dopasowaniu [jest równoważne Twojemu trzeciemu przykładowi] (https://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-440003.12)) się udaje. – duplode
@duplode, myślę, że leniwe domyślne ustawienie w 'let' i' where' było złym pomysłem, i jest to powód, dla którego czasami mogą być mylące wzorce. – dfeuer
@dfeuer Co z wiązaniem z nieskończoną listą? Na przykład 'let nats = [1 ..] w takeWhile isOkay nats' – Teodor
Natychmiastowa odpowiedź byłaby „ponieważ nie można przedefiniować co' 5' jest”. Jednak jestem całkiem zaskoczony, pisząc "let 5 = 10", który jest nawet możliwy! – duplode
co możesz zrobić, to 'przeciążać'' + ':' let 1 + 1 = 3 in 1 + 1';) – Carsten
btw: Myślę, że '5' w' let 5 = 10' jest nadal wzorcem (just taki, który nigdy nie jest dopasowany), więc nie będzie niczego wiązał (jak w 'let (x, 5) = (6,6)') – Carsten