2012-08-13 20 views
5

Loại return "abc" khi được in bằng ghci là gì?Loại nào được chọn cho một biểu thức đa hình khi được in?

Mấu chốt của vấn đề là nó đa hình trong đơn nguyên:

ghci> :t return "abc" 
return "abc" :: (Monad m) => m [Char] 

và những gì được in phụ thuộc vào đơn nguyên được chọn:

ghci> return "abc" :: Maybe String 
Just "abc" 

ghci> return "abc" :: [] String 
["abc"] 

nhưng đây là những gì đang thực sự in:

ghci> return "abc" 
"abc" 
+5

IO. Một phiên ghci giống như một IO Monad khổng lồ đặc biệt! – is7s

Trả lời

7

Khi bạn gõ một biểu expr vào GHCi, những điều sau đây xảy ra:

  • Khái niệm là loại kiểm tra. Nếu có lỗi, GHCi sẽ cho bạn biết lỗi và từ bỏ.
  • Nếu không, hãy nói expr được tìm thấy có loại t; GHC cố gắng đối sánh t với số IO a.
  • Nếu thành công, sau đó nó thực hiện một cái gì đó như it <- expr, sau đó nếu a là một thể hiện của Show và không phải là (), nó thực hiện print it.
  • Nếu nó không thành công, và t chính nó là một thể hiện của Show, GHCi làm điều gì đó như let it = expr và sau đó print it.
  • Nếu không, nó sẽ than phiền.

Về cơ bản, bạn cần một dấu nhắc của lệnh GHCi khi chạy các hành động IO và nhận các giá trị mà chúng quay lại và chơi với các giá trị thuần túy và nhìn thấy những gì bạn nhận được. Đó là lý do tại sao GHCi hành xử theo cách của nó: nếu nó có vẻ như bạn đang sử dụng một hành động IO, GHCi sẽ làm điều đó, và sau đó nếu hành động đó có kết quả có thể được hiển thị và thú vị (tức là không ()) thì nó cho thấy kết quả cho bạn. Nếu nó không thể hiển thị kết quả cho bạn, thì đó không phải là vấn đề lớn, bởi vì bạn có thể chỉ muốn chạy tác vụ IO; nếu bạn muốn kết quả bạn đã đặt tên nó với <-. Mặt khác, nếu có vẻ như biểu thức của bạn là không một hành động IO, GHCi sẽ tính toán nó và hiển thị nó cho bạn và nếu không thể hiển thị thì GHCi không thể làm gì hữu ích (không có tác dụng phụ nào thời gian), do đó, than phiền.

Trong trường hợp này, return "abc" typechecks như IO String, và String là một thể hiện của Show, vì vậy GHCi làm điều gì đó như

it <- return "abc" 
print it 

mà theo pháp luật đơn nguyên là chính xác giống như chỉ làm

print "abc" 

do đó là kết quả.

4

Haskell có bộ quy tắc hơi khó hiểu để quyết định loại các biểu thức liên quan đến các con số; bạn có thể thấy số Report section on ambiguous types and default instances. Vì vậy, câu trả lời cho câu hỏi chung là phức tạp. Nhưng trong vòng GHCi, nếu bạn nhập một biểu thức e, bạn có thể dựa trên các quy tắc áp dụng:

  • Nếu biểu thức e có thể được gõ như IO T đối với một số loại T, và nếu TShow thể hiện, GHCi sẽ chạy tính toán và in giá trị kết quả của loại T. Đó là những gì đang xảy ra trong ví dụ thứ ba của bạn.

  • Nếu biểu thức e * không thể * được gõ trong IO đơn nguyên, sau đó các quy tắc mặc định sơ thẩm đi vào chơi, và GHCi sẽ chọn một loại theo những quy tắc. Nếu loại có ví dụ Show thì GHCi sẽ in showe. Đó là những gì xảy ra trong hai ví dụ đầu tiên của bạn: Maybe String[String] là các giá trị thuần túy với Show trường hợp.

    Nếu loại e 's không không có một trường hợp Show, sau đó GHCi sẽ phàn nàn. Điều đó sẽ xảy ra nếu bạn nhập một biểu thức như flip take.

+2

Tôi nghĩ thực tế là câu hỏi rõ ràng về ghci và các quy tắc khác nhau ở đó khiến cho vài câu đầu tiên gây hiểu nhầm. Hơn nữa, GHCi không cố gắng in kết quả của các hành động 'IO' mà bạn gõ vào nếu kiểu có liên quan không phải là' Hiển thị' được, hoặc nếu nó là '()'. Tôi không chắc chắn nếu không có nhiều quy tắc là tốt. Ngoài ra, các quy tắc mặc định của GHCi mạnh hơn tiêu chuẩn của Haskell. –

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