2013-02-19 37 views
12

Tôi nghĩ rằng tôi hiểu được danh sách đơn lẻ nhưng sau đó tôi thấy tôi không. Đây là câu chuyện.(>) có phải loại bỏ tất cả các đầu ra bên trái không?

Với danh sách m và chức năng k

> let m = [1..10] 
> :t m 
m :: [Integer] 

> let k = replicate 2 
> :t k 
k :: a -> [a] 

Chơi với ràng buộc >>= cho những gì tôi mong đợi

> :t (>>=) 
(>>=) :: Monad m => m a -> (a -> m b) -> m b 
> :t m >>= k 
m >>= k :: [Integer] 
> m >>= k 
[1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10] 

nhưng đối với >>

dự kiến ​​(từ trải nghiệm với IO đơn nguyên, tất cả mọi thứ trên trái bên sẽ bị hủy)

m >> m 
[1,2,3,4,5,6,7,8,9,10] 

Got

> :t (>>) 
(>>) :: Monad m => m a -> m b -> m b 
:t m >> m 
m >> m :: [Integer] 
> m >> m 
[1,2,3,4,5,6,7,8,9,10,1,2,3,4,5 ... 9,10] -- truncated, real output is 100 elements 

Xin giải thích lý do tại sao >> không cư xử như tôi mong đợi (tất nhiên tôi phải có sự hiểu lầm) và cách chính xác để giải thích >> là gì?

Trả lời

25

(>>) loại bỏ giá trị khỏi đối số đầu tiên, nhưng không phải là hiệu ứng. Trong trường hợp này, có thể dễ dàng hơn nếu bạn sử dụng danh sách với các loại khác nhau:

λ> "ab" >> [1,2,3,4] 
[1,2,3,4,1,2,3,4] 

Lưu ý cách giá trị của danh sách đầu tiên không được sử dụng.

Hãy nhớ định nghĩa của (>>): a >> b = a >>= (\_ -> b). Vì vậy, điều này biến thành "ab" >>= (\_ -> [1,2,3,4]), tức là concat (map (\_ -> [1,2,3,4]) ['a','b']), tức là concat [[1,2,3,4],[1,2,3,4]] (cũng, [i | _ <- "ab", i <- [1,2,3,4]]).

Với [], (>>=) có nghĩa là một cái gì đó như "cho mỗi". Hàm bên phải sẽ là đối số cho mỗi giá trị ở bên trái. Vì vậy, (>>), loại bỏ các giá trị, vẫn có nghĩa là "cho mỗi" - nhưng lần này nó không thể sử dụng giá trị, vì vậy nó chỉ có nghĩa là "các phần tử của danh sách thứ hai, được lặp lại nhiều lần như có các yếu tố trong danh sách đầu tiên ".

+0

Wow! câu trả lời rõ ràng (và rất nhanh). Cảm ơn – wizzup

12

foo >> bar giống với foo >>= \_ -> bar. Vì vậy, trong trường hợp của IO nó thực hiện hành động trái, bỏ qua giá trị trả về của hành động đó, và sau đó thực hiện hành động đúng. Trong trường hợp danh sách, nó ánh xạ qua từng phần tử trong danh sách bên trái, bỏ qua giá trị của từng phần tử và chèn danh sách đúng vào mỗi điểm.

Một cách khác để xem nó là >>= cho danh sách giống như flip concatMap, >> giống với flip (concatMap . const).

+0

Cảm ơn bạn quá, Để xấu mà tôi chỉ có thể chọn một câu trả lời được chấp nhận. – wizzup

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