2012-04-18 11 views
11

Zauważyłem, że następujący kod daje błąd podczas próby go skompilować:Dlaczego seq computation builder nie pozwala na "let!"

let xx = 
    seq { 
    let! i = [ 1; 2 ] 
    let! j = [ 3; 4 ] 
    yield (i,j) 
    } 

Błąd ten daje to "Błąd FS0795:«niech x = coll»Stosowanie w wyrażeniach sekwencji nie jest Dłuższe zezwolenie Zamiast tego użyj "dla x w coll" "Ta wiadomość jest oczywista i pokazuje, jak to naprawić; naprawiony kod będzie:

let xx = 
    seq { 
    for i in [ 1; 2 ] do 
     for j in [ 3; 4 ] do 
     yield (i,j) 
    } 

Moje pytanie nie brzmi, jak to naprawić, ale dlaczego "niech!" nie jest dozwolone w wyrażeniach sekwencji w pierwszej kolejności? Widzę, jak to się stało! iteracje nad wyrażeniem mogą być dla niektórych zaskoczeniem, ale nie powinno to wystarczyć, aby nie pozwolić na konstrukt. Widzę też, jak "dla" jest tutaj potężniejsze, jako wersja z "niech!" piecze w zakresie iteracji jako "do końca wyrażenia sekwencji".

Jednak możliwość powtórzenia sekwencji bez wcięcia kodu była dokładnie tym, czego szukałem (do przechodzenia przez struktury drzewiaste). Zakładam, że aby uzyskać to semantyczne, będę musiał stworzyć nowy konstruktor wyrażeń, który działa głównie jak budowniczy wyrażeń "seq", ale pozwala na "niech!" do iteracji, prawda?


dodane, oparte na komentarz Briana poniżej, dostarczając rozwiązania mojego problemu: bazowego

Nie wiedziałem wcięcie w dla bloków nie jest potrzebna, a druga próbkę można ponownie zapisać jako:

let xx = 
    seq { 
    for i in [ 1; 2 ] do 
    for j in [ 3; 4 ] do 
    yield (i,j) 
    } 

... który pozbywa się coraz nacięciu gdy przejeżdżające strukturę drzewa. Składnia pozwala nawet dodatkowych oświadczeń w między dla wypowiedzi bez konieczności dodatkowego wcięcia, jak w:

let yy = 
    seq { 
    for i in [ 1; 2 ] do 
    let i42 = i+42 
    for j in [ 3; 4 ] do 
    yield (i42,j) 
    } 

Teraz, jeśli tylko mogę zrozumieć dlaczego myślałem, oświadczenia te wymagałyby wcięcia ...

+4

Możliwe zamieszanie z 'let!' W powiązaniach asynchronicznych - mamy identyczną składnię, robiąc zupełnie różne rzeczy? –

+1

Czy próbowałeś "forów bez wcięć? – Brian

+0

@Brian "Czy próbowałeś" forów bez wcięć? " - nie, z jakiegoś powodu nie zdawałem sobie sprawy, że wcięcia w "forach" nie są potrzebne. Dzieki za sugestie! Ściśle mówiąc, nie odpowiada na pytanie, ale zapewnia akceptowalne podejście do pracy, więc w pewnym sensie odpowiada na moje pytanie. –

Odpowiedz

8

Zaledwie kilka tygodni temu napisałem artykuł z Don Syme, który próbuje wyjaśnić niektóre motywy wyboru składni w wyrażeniach obliczeniowych F # (takich jak wyrażenia sekwencji, asynchroniczne przepływy pracy i inne). Możesz find it here. Nie daje jednoznacznej odpowiedzi na twoje pytanie, ale może pomóc.

W ogóle, gdy masz jakiś rodzaj M<'T> i jesteś definiowania obliczeń konstruktora, można dodać metody For i Bind włączyć for i let! składnię:

For : seq<'T> -> ('T -> M<'T>) -> M<'T> 
Bind : M<'T> -> ('T -> M<'T>) -> M<'T> 

Wejście dla For powinny być zawsze pewne sekwencja seq<'T>, natomiast wejście dla Bind powinno być typu M<'T>, dla którego je definiujesz.

W wyrażeniach sekwencji te dwie operacje miałyby ten sam typ, więc musiałyby zrobić to samo. Mimo że wyrażenia sekwencyjne mogą zapewnić jedno i drugie, prawdopodobnie dobrym pomysłem jest zezwolenie na jedno, ponieważ użycie dwóch różnych słów kluczowych na jedną rzecz byłoby mylące.Ogólną zasadą jest, że kod w bloku comp { .. } powinien zachowywać się jak normalny kod - a ponieważ for istnieje w normalnym kodzie F #, ma sens użycie tej samej składni w wyrażeniu obliczeniowym dla seq<'T>.

+1

Dzięki za wyjaśnienie! Osobiście myślę, że zostawiłbym obie opcje składni, ponieważ pociąg myślący prowadzący do każdego z nich może być inny, nawet jeśli są one funkcjonalnie takie same. W moim przypadku szukałem operacji, która pasowała do podpisu Binda dla M <'T>, które mogłyby stanowić pewnego rodzaju kolekcję "T. Później zdałem sobie sprawę, że dobre stare seq <'T> zrobiły już wszystko, czego potrzebowałem, więc spróbowałem użyć Bind of seq {...}, co oznaczało napisanie "niech!" wewnątrz wyrażenia seq {...}. Właśnie tam wpadłem na komunikat o błędzie ... –

+2

Niezły papier, Tomas! – Daniel

+1

Link do papieru daje obecnie numer 404, czy istnieje inny sposób jego znalezienia? – VisualMelon

Powiązane problemy