2011-11-05 15 views
24

Jak uczę Haskell Mam świadomość, że do notacja jest cukier tylko syntatic:Desugaring zrobić, notacja dla monad

a = do x <- [3..4] 
     [1..2] 
     return (x, 42) 

przekłada się

a = [3..4] >>= (\x -> [1..2] >>= (\_ -> return (x, 42))) 

Zdaję sobie sprawę, że będę prawdopodobnie używaj do-notacji, ale chciałbym zrozumieć, co się dzieje w tłumaczeniu. Czyli czysto ze względów pedagogicznych, czy istnieje sposób, aby ghc/ghci dał mi odpowiednie instrukcje wiążące dla dość złożonej monady zapisanej w notacji do-notacji?

Edytuj. Okazuje się lambdabot na #haskell można to zrobić:

<Guest61347> @undo do x <- [3..4] ; [1..2] ; return (x, 42) 
<lambdabot> [3 .. 4] >>= \ x -> [1 .. 2] >> return (x, 42) 

Oto kod źródłowy Undo plugin.

+3

faktycznie 'm >> = (\ _ -> k)' jest 'm >> k' –

+7

Lambdabot ma wtyczkę" cofnij ", którą wyrecytował zapis. –

+1

Po prostu uczę się i czuję, że to jest klucz do zrozumienia szczegółów konkretnej instancji - wszystkie są napisane w kategoriach >> = –

Odpowiedz

18

Możesz zapytać o wynik desugarera GHC, jednak spowoduje to również wiele innych składni.

Najpierw kładziemy swój kod w module Foo.hs:

module Foo where 

a = do x <- [3..4] 
     [1..2] 
     return (x, 42) 

Następny zadamy GHC do niej i wyjście wynik po fazie desugaring kompilacji:

$ ghc -c Foo.hs -ddump-ds 

Wynik może wyglądać raczej niechlujnie, ponieważ jest to wariant Haskella zwany Core, który jest używany jako język pośredni GHC. Jednak nie jest to zbyt trudne do odczytania, gdy się do tego przyzwyczaisz. W środku niektórych innych definicji znaleźć swoje:

Foo.a :: [(GHC.Integer.Type.Integer, GHC.Integer.Type.Integer)] 
LclIdX 
[] 
Foo.a = 
    >>=_agg 
    @ GHC.Integer.Type.Integer 
    @ (GHC.Integer.Type.Integer, GHC.Integer.Type.Integer) 
    (enumFromTo_ag7 
     (GHC.Integer.smallInteger 3) (GHC.Integer.smallInteger 4)) 
    (\ (x_adf :: GHC.Integer.Type.Integer) -> 
     >>_agn 
     @ GHC.Integer.Type.Integer 
     @ (GHC.Integer.Type.Integer, GHC.Integer.Type.Integer) 
     (enumFromTo_ags 
      (GHC.Integer.smallInteger 1) (GHC.Integer.smallInteger 2)) 
     (return_aki 
      @ (GHC.Integer.Type.Integer, GHC.Integer.Type.Integer) 
      (x_adf, GHC.Integer.smallInteger 42))) 

rdzeń nie jest zbyt ładna, ale jest w stanie odczytać to jest bardzo przydatne podczas pracy z GHC, jak można odczytać zrzut po późniejsze etapy zobaczyć jak GHC optymalizuje twój kod.

Jeśli usuwamy _xyz przyrostków dodanych przez renamer, jak również aplikacje typu @ Xyz i wezwań do GHC.Integer.smallInteger, i sprawiają, że operatorzy infix znowu jesteś w lewo z czegoś takiego:

Foo.a :: [(GHC.Integer.Type.Integer, GHC.Integer.Type.Integer)] 
Foo.a = enumFromTo 3 4 >>= \x -> enumFromTo 1 2 >> return (x, 42) 
+4

Który nasuwa pytanie ... czy jest coś, co automatycznie usunie sufiksy _xyz, wpisz podanie komunikaty do GHC.Integer.smallInteger i sprawiają, że operatorzy ponownie infiksują? – hugomg

+1

@missingno: Brak, o którym jestem świadomy. Istnieją jednak biblioteki dostępne do pracy z Haskellem lub Core na Hackage, więc nie powinno być zbyt trudno zhakować coś razem, jeśli chcesz tego wystarczająco źle. – hammar

+2

Kłopot w tym, że do czasu napisania kodu, aby to zrobić, już go nie potrzebujesz. –