2011-11-05 23 views
24

Như tôi đang học Haskell Tôi nhận ra rằng do ký hiệu chỉ là syntatic đường:Desugaring làm-ký hiệu cho Monads

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

chuyển thành

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

Tôi nhận ra rằng tôi sẽ có thể sử dụng ký hiệu nhưng tôi muốn hiểu những gì đang diễn ra trong bản dịch. Vì vậy, hoàn toàn vì lý do sư phạm, có cách nào để ghc/ghci đưa cho tôi các câu lệnh ràng buộc tương ứng cho một đơn nguyên khá phức tạp được viết bằng ký hiệu không?

Chỉnh sửa. Hóa ra lambdabot trên #haskell có thể làm điều này:

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

Đây là mã nguồn Undo plugin.

+3

thực sự 'm >> = (\ _ -> k)' là 'm >> k' –

+7

Lambdabot có một plugin" hoàn tác "mà desugars làm ký hiệu –

+1

Tôi chỉ học và cảm thấy như thế này là chìa khóa để thực sự hiểu chi tiết của một trường hợp cụ thể - tất cả chúng đều được viết dưới dạng >> = –

Trả lời

18

Bạn có thể yêu cầu đầu ra của desugarer của GHC, tuy nhiên điều này cũng sẽ desugar rất nhiều cú pháp khác.

Thứ nhất, chúng tôi sẽ đặt mã của bạn trong một module Foo.hs:

module Foo where 

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

Tiếp theo, chúng tôi sẽ hỏi GHC để biên dịch nó và đầu ra là kết quả sau khi giai đoạn desugaring:

$ ghc -c Foo.hs -ddump-ds 

Đầu ra có thể trông khá lộn xộn, bởi vì nó là một biến thể của Haskell được gọi là Core được sử dụng làm ngôn ngữ trung gian của GHC. Tuy nhiên, nó không quá khó đọc khi bạn quen với nó. Ở giữa một số định nghĩa khác mà chúng tôi tìm thấy bạn:

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))) 

Core là không quá xinh đẹp, nhưng có thể đọc nó là rất hữu ích khi làm việc với GHC, như bạn có thể đọc các bãi sau giai đoạn sau để xem cách GHC tối ưu hóa mã của bạn.

Nếu chúng ta loại bỏ các _xyz hậu tố bổ sung bởi các đổi tên, cũng như các ứng dụng loại @ Xyz và các cuộc gọi đến GHC.Integer.smallInteger, và làm cho các nhà khai thác ghi vào một lần nữa, bạn lại với một cái gì đó như thế này:

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

Điều gì đặt ra câu hỏi ... là có điều gì đó ngoài đó sẽ tự động xóa hậu tố _xyz, loại ứng dụng hành, gọi tới GHC.Integer.smallInteger và thực hiện lại các thao tác? – hugomg

+1

@missingno: Không có gì tôi biết. Tuy nhiên, có các thư viện có sẵn để làm việc với Haskell hoặc Core trên Hackage, vì vậy không nên quá khó khăn để hack một thứ gì đó với nhau nếu bạn muốn nó đủ tồi tệ. – hammar

+2

Vấn đề là, vào lúc bạn viết mã để làm điều đó, bạn không cần nó nữa. –

Các vấn đề liên quan