2013-09-27 120 views
8

Mã này rõ ràng làm việcKhông sử dụng một biến cho <-

import Data.Char 

main = do 
    content <- readFile "in.txt" 
    writeFile "out.txt" (map toUpper content) 

Tại sao cái này không?

import Data.Char 

main = do 
    writeFile "out.txt" (map toUpper $ <- readFile "in.txt") 

Trả lời

17

Bởi vì đây không phải là cách <- được định nghĩa. Nó dịch để

readFile "in.txt" >>= \content -> 
writeFile "out.txt" (map toUpper content) 

Bạn có thể sử dụng thay vì =<<:

writeFile "out.txt" . map toUpper =<< readFile "in.txt" 
3

bạn có thể viết nó như sau

readFile "in.txt" >>= writeFile "out.txt" . map toUpper 
+0

Hoặc 'bản đồ toUpper <$> readFile" in.txt ">> = writeFile" out.txt "'. Tuy nhiên tôi nghĩ rằng OP muốn một lời giải thích và không phải là một giải pháp đơn thuần – nponeccop

17

Thứ nhất, <- không phải là một nhà điều hành. Đó là một phần tử cú pháp đặc biệt yêu cầu một mẫu ở phía bên trái.

Thứ hai, nếu đó là một toán tử kết hợp, $ <- sẽ không hoạt động, vì bạn không thể có hai toán tử infix bên cạnh nhau.

6

<- "chiết xuất" một giá trị từ vùng chứa đơn sắc. IO là một đơn nguyên và do đó, nó có thể được sử dụng để trích xuất một giá trị từ hành động IO. Tuy nhiên, cú pháp của Haskell nói rằng bạn phải liên kết nó với tên trước khi sử dụng. Trong thực tế, các <- không phải là một nhà điều hành ở tất cả, nhưng cú pháp đường cho các nhà điều hành >>= (phát âm là "ràng buộc"). Vì vậy, khi bạn viết

main = do 
    contents <- readFile "in.txt" 
    writeFile "out.txt" (map toUpper contents) 

Nó bị biến thành

main = readFile "in.txt" >>= (\contents -> writeFile "out.txt" (map toUpper contents)) 

Bây giờ, hãy tưởng tượng nếu bạn đã có rất nhiều nhiều câu lệnh trong main. Có thể bạn đã trích xuất một vài giá trị với <- và một số cụm từ được sử dụng nhiều hơn một trong các giá trị đó tại một thời điểm. Bạn chắc chắn có thể viết "desugared" phiên bản, nhưng nó sẽ bắt đầu nhận được rất, rất khó khăn. Các ký hiệu làm đơn giản hóa điều này và làm cho trình biên dịch chăm sóc nó cho bạn.