2012-04-18 29 views
6

Say Pisałem następujące amazin kawałek kodu:"<-" i wartości związanych

func = do 
    a <- Just 5 
    return a 

To dość bezcelowe, wiem. Tutaj a jest 5 i func zwraca Just 5.

Teraz przerobić moje niesamowite funkcji (jeszcze bezsensowną):

func' = do 
    a <- Nothing 
    return a 

Funkcja ta zwraca Nothing, ale co do cholery jest a? Nie ma nic, aby wyodrębnić z wartości Nothing, ale program nie jęcz, kiedy robię coś takiego:

func'' = do 
    a <- Nothing 
    b <- Just 5 
    return $ a+b 

prostu trudno zobaczyć, co faktycznie się dzieje. Co to jest a? Innymi słowy: co robi teraz? Mówienie "wyodrębnia wartość z prawej strony i wiąże ją z lewą stroną", oczywiście upraszcza ją. Czego nie dostaję?

Dzięki :)

+1

'<-' tłumaczy się na" >>. W przypadku monady "Maybe", jeśli pierwszym argumentem (tj. Częścią prawa do '<-') jest" Nic ", nic innego nie jest oceniane, a' >> = 'po prostu zwraca' Nothing'. Tak więc, aby odpowiedzieć na twoje pytanie: egzekucja nie ma nawet _reach_ "a". – Vitus

+0

Myśląc o monadach jako kontenerach, notacja doładowania pozwala przypisać etykiety do wartości (jeśli występują) wewnątrz monad, a następnie zdefiniować funkcje, które zostaną zastosowane do tych wartości. Ale ekstrakcja jest iluzją - funkcje są stosowane wewnątrz monady (używając '>> ='), ponieważ nie ma ogólnego sposobu wydobycia wartości z monady. Zwróć uwagę, jak kończysz każdy blok do-do-bloku, umieszczając wynik _back w monad_, często używając 'return'. Nigdy tak naprawdę nie miałeś zmiennej "a", która byłaby równa 5. – Nefrubyr

Odpowiedz

11

Spróbujmy desugar do-notację tego ostatniego przykładu.

func'' = Nothing >>= (\a -> Just 5 >>= (\b -> return $ a+b)) 

Teraz zobaczmy, jak >> = jest zdefiniowany dla Może. Jest w Prelude:

instance Monad Maybe where 
    (Just x) >>= k = k x 
    Nothing >>= k = Nothing 
    return   = Just 
    fail s   = Nothing 

Więc Nothing >>= foo jest po prostu Nothing

+0

Dziękuję :) Domyślam się, że nie jestem zbyt dobry w usuwaniu notacji ... – Undreren

+1

Każdy foo <- bar podąża za paskiem schematu >> = (\ foo -> ...). Teraz możesz także zobaczyć, dlaczego na końcu każdego bloku do-do musi być wyrażenie, lub jedno z tych (prawdopodobnie zagnieżdżonych) wyrażeń lambda ma pustą treść funkcji. Być może ten link pomoże: http://book.realworldhaskell.org/read/monads.html#monads.do – Sarah

5

Przyjrzyjmy się definicji Maybe monady.

instance Monad Maybe where 
    return = Just 

    Just a >>= f = f a 
    Nothing >>= _ = Nothing 

I desugar na do -notation w swojej funkcji:

func' = 
    Nothing >>= \a -> 
    return a 

Pierwszym argumentem >>= jest Nothing i z definicji powyżej widzimy, że >>= prostu ignoruje drugi argument. Tak więc otrzymujemy:

func' = Nothing 

Ponieważ funkcja \a -> ... nigdy nie jest wywoływana, a nigdy nie zostanie przypisany. Tak więc odpowiedź brzmi: a nie został jeszcze osiągnięty.


chodzi o desugaring do -notation, oto szybki szkic jak to się robi (jest jeden uproszczenie zrobiłem - obsługa fail, czyli wzorce, które nie pasują):

do {a; rest} → a >> do rest 

Zauważ, że >> jest zwykle zaimplementowane pod względem >>= jako a >>= \_ -> do rest (tj. Druga funkcja po prostu ignoruje argument).

do {p <- a; rest} → a >>= \p -> do rest 

do {let x = a; rest} → let x = a in do rest 

I wreszcie:

do {a} = a 

Oto przykład:

main = do 
    name <- getLine 
    let msg = "Hello " ++ name 
    putStrLn msg 
    putStrLn "Good bye!" 

desugars do:

main = 
    getLine >>= \name -> 
    let msg = "Hello " ++ name in 
    putStrLn msg >> 
    putStrLn "Good bye!" 

i T O zrobić to kompletna dla tych, którzy są ciekawi, tutaj jest „prawo” tłumaczenie do {p <- a; rest} (zaczerpnięte bezpośrednio z raportu Haskell):

do {pattern <- a; rest} → let ok pattern = do rest 
           ok _  = fail "error message" 
          in a >>= ok 
6

Odpowiedź leży w definicji instancji Monad z Maybe:

instance Monad Maybe where 
    (Just x) >>= k  = k x 
    Nothing >>= _  = Nothing 
    (Just _) >> k  = k 
    Nothing >> _  = Nothing 
    return    = Just 

Twój func'' przekłada się:

Nothing >>= (\a -> (Just 5 >>= (\b -> return (a+b)))) 

z definicji (>>=) widać, że pierwszy Nothing jest po prostu przechodzący do wyniku.

2

Nothing nie jest naprawdę „nic”, to faktycznie możliwa wartość czegoś w Maybe monady:

data Maybe t = Nothing | Just t 

Oznacza to, że jeśli masz coś typu Maybe t jakiegoś rodzaju t, może mieć wartość Just x (gdzie x jest czymkolwiek typu t) lubNothing; w tym sensie Maybe po prostu rozszerza t, aby mieć jedną możliwą wartość, Nothing. (To ma inne właściwości, ponieważ jest to monad, ale to tak naprawdę nie dotyczy nas tutaj, z wyjątkiem cukru składniowej z do i <-.)

1

Weźmy swój przykład:

func = do 
    a <- Just 5 
    return a 

podobnie jak w inne języki programowania, które można podzielić na dwie części, odpowiadają "temu, co zostało zrobione do tej pory" i "co jest jeszcze do zrobienia". Na przykład możemy zrobić przerwę między Just 5 i

a <- ... 
return a 

W wielu popularnych języków programowania oczekujesz Just 5 być nadziewane w zmiennej a a kod będzie kontynuowany.

Haskell robi coś innego. "Reszta kodu" może być traktowana jako funkcja opisująca, co zrobiłbyś z a, gdybyś miał jakąś wartość, aby ją umieścić. Ta funkcja jest następnie stosowana do Just 5. Ale nie stosuje się bezpośrednio. Jest stosowany z dowolną definicją, zależnie od typu wyrażenia. Dla parametru Maybe, >>= zdefiniowano tak, że w przypadku funkcji Just X funkcja "reszta kodu" jest stosowana do X.Ale jest również zdefiniowany, więc gdy mamy do czynienia z Nothing, funkcja "reszta kodu" jest po prostu ignorowana i zwracana jest nazwa Nothing.

Możemy teraz zinterpretować twój drugi przykład

func'' = do 
    a <- Nothing 
    b <- Just 5 
    return $ a+b 

podzielić go na Nothing i:

a <- ... 
    b <- Just 5 
    return $ a+b 

Jak powiedziałem wyżej, to blok kodu mogą być traktowane funkcji przyłożonego do ewentualnego wartość a. Ale jest używany z Nothing iw tym przypadku zdefiniowano >>=, aby zignorować "resztę kodu" i po prostu zwrócić Nothing. I to jest rezultat, który otrzymałeś.

Powiązane problemy