Tôi đang giúp một người bạn học Haskell và gần đây ông đã tạo mã như thế này, loại này kiểm tra và tạo ra một vòng lặp CPU-cháy khi chạy. Tôi hoàn toàn bối rối bởi điều này.Tại sao nhập Control.Applicative cho phép mã này xấu gõ kiểm tra?
import Control.Monad
import Control.Applicative
main = forever putStrLn "Hello, infinity"
Đó không phải là loại séc, nhưng có. Phiên bản đúng sẽ là rõ ràng:
main = forever $ putStrLn "Hello, infinity"
Có gì kỳ lạ và đáng ngạc nhiên đối với tôi là bạn có được kết quả khác nhau có và không có nhập khẩu Control.Applicative. Nếu không nhập nó, nó không gõ kiểm tra:
Prelude Control.Monad> forever putStrLn "Hello, infinity"
<interactive>:1:1:
No instance for (Monad ((->) String))
arising from a use of `forever'
Possible fix: add an instance declaration for (Monad ((->) String))
In the expression: forever putStrLn "Hello, infinity"
In an equation for `it': it = forever putStrLn "Hello, infinity"
Tôi không thấy một ví dụ đơn nguyên cho ((->) String
trong nguồn cho Control.Applicative, vì vậy tôi đoán điều gì đó kỳ lạ đang xảy ra do việc sử dụng các Control.Category hoặc Control.Arrow, nhưng tôi không biết. Vì vậy, tôi đoán tôi có hai câu hỏi:
- Điều gì sẽ xảy ra với việc nhập Control Control.Applicative cho phép điều này xảy ra?
- Điều gì sẽ xảy ra khi nó đi vào vòng lặp vô hạn? Haskell thực sự đang cố gắng thực hiện trong trường hợp đó là gì?
Cảm ơn,
Bạn có thể giải thích về ví dụ cho '(->) e' nào hữu ích không? –
@DanielLyons Rất hữu ích khi bạn có nhiều chức năng mà tất cả đều cần quyền truy cập vào một số thông tin cấu hình được chia sẻ. Sau đó, bạn có thể viết (ví dụ) 'foo >> = bar >> = baz' thay vì lặp lại môi trường ở khắp mọi nơi như trong' \ e -> let x = foo e; y = bar x e; z = baz y e trong y'. –