2013-01-10 29 views
15

Khi thực hiện hành động IO được xác định bởi someFun <$> (a :: IO()) <$> (b :: IO()), việc thực thi các hành động ab có được yêu cầu không? Tức là, tôi có thể dựa vào số a đó được thực thi trước b không?Haskell - Có phải xác định thứ tự có hiệu lực trong trường hợp Áp dụng không?

Đối với GHC, tôi có thể thấy IO được thực hiện bằng cách sử dụng trạng thái, và cũng xem here rằng nó là một thể hiện áp dụng, nhưng không thể tìm thấy nguồn gốc của khai báo cá thể thực tế. Việc triển khai thực hiện thông qua Nhà nước cho thấy rằng các hiệu ứng IO khác nhau cần phải được tuần tự, nhưng không cần thiết xác định thứ tự của chúng.

Chơi xung quanh trong GHCi có vẻ như Appliative vẫn giữ lại trật tự hiệu lực, nhưng đó là một số đảm bảo phổ quát, hoặc GHC cụ thể? Tôi sẽ quan tâm đến chi tiết.

import System.Time 
import Control.Concurrent 
import Data.Traversable 
let prec (TOD a b) = b 
fmap (map prec) (sequenceA $ replicate 5 (threadDelay 1000 >> getClockTime)) 

[641934000000,642934000000,643934000000,644934000000,645934000000] 

Cảm ơn!

+0

Tôi đoán bài đăng này chứa thông tin hữu ích nhưng tôi vẫn phải tiêu hóa nó: http://pchiusano.blogspot.hu/2011/07/do-side-effects-really-need-total-order.html – ron

+4

Xem http : //hackage.haskell.org/packages/archive/transformers/0.3.0.0/doc/html/Control-Applicative-Backwards.html, là một biến áp ứng dụng đảo ngược thứ tự các hiệu ứng. –

Trả lời

18

Chắc chắn là xác định, vâng. Nó sẽ luôn luôn làm điều tương tự cho bất kỳ trường hợp cụ thể nào. Tuy nhiên, không có lý do nào là vốn có của tài khoản cố định để chọn từ trái sang phải từ phải sang trái cho thứ tự hiệu ứng.

Tuy nhiên, từ the documentation for Applicative:

Nếu f cũng là một Monad, cần đáp ứng pure = return(<*>) = ap (mà ngụ ý rằng pure<*> đáp ứng các luật functor applicative).

Định nghĩa của ap là thế này, từ Control.Monad:

ap :: (Monad m) => m (a -> b) -> m a -> m b 
ap = liftM2 id 

liftM2 được định nghĩa theo cách rõ ràng:

liftM2 f m1 m2 = do { x1 <- m1; x2 <- m2; return (f x1 x2) } 

Điều này có nghĩa là, đối với bất kỳ functor đó là a Monad cũng như Applicative, dự kiến ​​(theo đặc điểm kỹ thuật, vì điều này không thể được thực thi trong mã), rằng Applicative sẽ hoạt động từ trái sang phải, để khối do trong liftM2 thực hiện tương tự như liftA2 f x y = f <$> x <*> y.

Vì trên, ngay cả đối với Applicative trường hợp không có tương ứng Monad, theo quy ước, các hiệu ứng thường được đặt hàng từ trái sang phải.

Thông thường hơn, vì cấu trúc của tính toán Applicative nhất thiết phải độc lập với "hiệu ứng", bạn thường có thể phân tích ý nghĩa của chương trình độc lập với hiệu ứng Applicative được giải trình tự. Ví dụ: nếu phiên bản cho [] được thay đổi thành chuỗi từ phải sang trái, bất kỳ mã nào sử dụng nó sẽ cho ra cùng một kết quả, chỉ với các phần tử danh sách theo một thứ tự khác.

+0

Cảm ơn bạn! Tôi có suy ra một cách chính xác rằng nếu thứ tự hiệu quả là quan trọng đối với tôi và tôi muốn trở thành lý thuyết thì tôi nên sử dụng một Monad, nhưng nếu tôi thực tế thì ứng dụng sẽ (phù hợp, cẩn thận) phù hợp? – ron

+2

@ron: Trong thực tế, bạn có thể chỉ đơn giản giả định rằng các trường hợp 'Applicative' sẽ tuần tự từ trái sang phải trừ khi chúng thông báo một cách to lớn, như với trình bao bọc' Backwards'. Lưu ý rằng các cá thể 'Monad' cũng có thể không rõ ràng theo những cách khác - ví dụ, toán tử' State' đã đảo ngược sẽ trả về giá trị trạng thái ngược lại, nhưng chính kiểu đó giống hệt với 'State' thông thường. Đối với một ví dụ khác, '[]' có hai trường hợp có thể 'áp dụng 'ngay cả ngoài thứ tự sắp xếp. Bạn không thể tránh dựa phần nào vào những gì tài liệu nói. –

+0

@ C.A.McCann "* [...] bạn thường có thể phân tích ý nghĩa của một chương trình độc lập với cách hiệu ứng ứng dụng được sắp xếp theo trình tự. *" Tại sao? Điều đó không chỉ đúng đối với các functors * commutative * applicative? Nói chung, sắp xếp lại các hiệu ứng áp dụng có thể thay đổi kết quả đáng kể. Dưới đây là một ví dụ: 'myParser = (++) <$> foo <*> thanh' trong đó' foo' và 'bar' là parsec' Chuỗi phân tích cú pháp'. Nếu tôi thay đổi trình tự từ phải sang trái, 'myParser' sẽ không thành công trên chuỗi đầu vào' "foobar" '. Bạn sẽ không đồng ý, trong trường hợp này, việc sắp xếp lại các hiệu ứng đã ảnh hưởng đến ý nghĩa của chương trình? – Jubobs

4

Có, thứ tự được xác định trước bằng thư từ Đơn-Ứng.Đây là dễ dàng nhận thấy: Các (*>) combinator cần phải tương ứng với (>>) combinator trong một well-behaved Applicative dụ cho một đơn nguyên, và định nghĩa của nó là:

a *> b = liftA2 (const id) a b 

Nói cách khác, nếu b được thực hiện trước khi a, thể hiện Applicative sẽ hoạt động không tốt.

Edit: Như một mặt lưu ý: Đây không phải là quy định một cách rõ ràng bất cứ nơi nào, nhưng bạn có thể tìm thấy nhiều thư từ tương tự khác như liftM2 = liftA2 vv

2

Đối với IO applicative, điều này chắc chắn là như vậy. Nhưng hãy kiểm tra các async package cho một ví dụ về một ứng dụng trong đó trong f <$> a <*> b các tác động của ab xảy ra song song.

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