2015-07-05 47 views
16

Tôi đang theo dõi this blog, để viết một máy chủ http đơn giản trong haskell,Control.Category, >>> và <<< có nghĩa là gì?

Cách sử dụng >>> không rõ ràng đối với tôi. Đoạn mã này làm gì?

handleHttpConnection r c = runKleisli 
    (receiveRequest >>> handleRequest r >>> handleResponse) c >> 
    close c 

Tương tự trên this link, tôi đang nhìn thấy <<<

let h =  arr (++ "!") 
      <<< arr foo 
      <<< Kleisli bar 
      <<< arr id 

<<<>>> làm gì? (Hackage document là rất súc tích và không thể có được nhiều ra khỏi nó.)

+1

Blog đó có [liên kết] (https://wiki.haskell.org/Arrow_tutorial#Kleisli_Arrows) đến một bài viết về Kleisli Mũi tên có vẻ hữu ích. Tôi tin rằng hai toán tử này đại diện cho một số loại thành phần hàm (cho các Mũi tên có chức năng). Đối với các loại Mũi tên khác, tôi không chắc, vì mũi tên hơi lạ với tôi. – jpaugh

Trả lời

20

Như Hackage và/hoặc Hoogle sẽ cho bạn biết,

(>>>) :: Category k => a`k`b -> b`k`c -> a`k`c 
(<<<) :: Category k => b`k`c -> a`k`b -> a`k`c 

Quan sát rằng sau này là thực sự giống như

(.) :: Category k => b`k`c -> a`k`b -> a`k`c 

hoặc, ở dạng Prelude của nó, đặc biệt với Hask chủng loại chức năng,

(.) ::    (b->c) -> (a->b) -> (a->c) 

Vì vậy, <<<>>> chỉ cần soạn các hàm, hoặc nhiều hình thái/mũi tên chung hơn.

<<< soạn theo hướng giống như quen thuộc ., trong khi >>> flips các đối số để “ dữ liệu chảy từ trái sang phải ”.


Bây giờ, những gì mũi tên thành phần nghĩa, cho các thể loại khác hơn Hask, phụ thuộc của khóa học về thể loại. Kleisli IO là dễ hiểu ví dụ: nói rằng chúng ta có một hàm thuần túy

pipe :: Double -> String 
pipe = show . sqrt . (+2) . abs 

Như tôi đã nói, điều này cũng có thể được viết

pipe = abs >>> (+2) >>> sqrt >>> show 

Bây giờ, nếu bạn muốn thêm nguyên thủy IO đăng nhập (giống như bạn có thể bằng ngôn ngữ bắt buộc), bạn có thể giới thiệu

type (-|>) = Kleisli IO 

abs', add2', sqrt' :: Num a => a -|> a 
show' :: Show a => a -|> String 

abs' = Kleisli $ \x -> do putStrLn ("Absolute of "++show x++"...") 
          return $ abs x 
add2' = Kleisli $ \x -> do putStrLn ("Add 2 to "++show x++"...") 
          return $ x + 2 
sqrt' = Kleisli $ \x -> do putStrLn ("Square root of "++show x++"...") 
          return $ sqrt x 
show' = Kleisli $ \x -> do putStrLn ("Show "++show x++"...") 
          return $ show x 

Với điều đó, bạn có thể xác định

pipe' :: Double -|> String 

trong chính xác theo cùng một cách như trước, ví dụ:

pipe' = abs' >>> add2' >>> sqrt' >>> show' 

Nhưng bây giờ bạn sẽ nhận được kết quả trung gian in ra như một tác dụng phụ.

+0

đó là một ví dụ đẹp ... cảm ơn ... tại sao một người nào đó sẽ làm 'show. sqrt. (+2). abs' thay vì 'show $ sqrt $ (+2) $ abs n'. tôi biết, dấu chấm '.' là tất cả về một số thành phần hàm, nhưng nó có giải quyết được bất kỳ vấn đề nào mà' $ 'không giải quyết được không? –

+2

@MadhavanKumar: tốt, đây là một ví dụ tuyệt vời cho những gì '$' không giải quyết: nó không thể được khái quát hóa để làm việc trong các thể loại tùy ý. ([Một số loại có tổng quát '$', nhưng hầu hết không - bao gồm 'Kleisli'] (http://stackoverflow.com/questions/31118949/generalising-like-control-category-generalises/31120454#31120454) Ngoài ra, phong cách điểm tự do thường ngắn gọn hơn, có thể được tái cấu trúc dễ dàng hơn một chút, và không yêu cầu bạn giới thiệu tên biến ... tuy nhiên, đây không phải lúc nào cũng có lợi thế; đôi khi không có điểm khó hiểu (“mã vô nghĩa”). – leftaroundabout

+1

Sau đó, là '<=<' and '> =>' cũng là trường hợp đặc biệt của '<<<' and '> >>' hoạt động cho các đơn nguyên? –

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