2011-12-16 24 views
6

Tôi có một số bản mẫu Haskell khá phổ biến xuất hiện ở nhiều nơi. Nó trông giống như thế này (khi instantiating lớp):Gỡ bỏ bản mẫu ống dẫn đường ống chung của số điện thoại

a <= b = (modify a) <= (modify b) 

như thế này (với các chức năng bình thường):

fn x y z = fn (foo x) (foo y) (foo z) 

và đôi khi ngay cả với các bộ, như trong:

mod (x, y) = (alt x, alt y) 

nó có vẻ như có một cách dễ dàng để giảm tất cả các bản mẫu này và không phải lặp lại bản thân mình khá nhiều. (Đây là những ví dụ đơn giản, nhưng nó gây khó chịu). Tôi tưởng tượng rằng có những trừu tượng được tạo ra để loại bỏ bản mẫu như vậy, nhưng tôi không chắc chắn những gì họ được gọi là cũng không phải nơi để tìm. Có thể bất kỳ haskellites điểm tôi đi đúng hướng?

Trả lời

12

Đối với trường hợp (<=), hãy xem xét việc xác định compare thay; sau đó bạn có thể sử dụng Data.Ord.comparing, như vậy:

instance Ord Foo where 
    compare = comparing modify 

Lưu ý rằng comparing chỉ có thể được định nghĩa là comparing f = compare `on` f, sử dụng Data.Function.on.

Ví dụ fn của bạn, không rõ. Không có cách nào để đơn giản hóa loại định nghĩa này nói chung. Tuy nhiên, tôi không nghĩ rằng boilerplate là quá xấu trong trường hợp này.

Đối mod:

mod = alt *** alt 

sử dụng Control.Arrow.(***) - đọc a b c như b -> c trong chữ ký loại; mũi tên chỉ là một trừu tượng chung (như functors hoặc monads) trong đó các hàm là một cá thể. Bạn có thể muốn xác định both = join (***) (chính nó là viết tắt của both f = f *** f); Tôi biết ít nhất một người khác sử dụng bí danh này, và tôi nghĩ rằng nó phải ở trong Control.Arrow đúng.

Vì vậy, nói chung, câu trả lời là: combinators, combinators, combinators! Điều này liên kết trực tiếp với phong cách point-free. Nó có thể là quá nhiều, nhưng khi các combinator tồn tại cho tình huống của bạn, mã như vậy không chỉ gọn gàng và ngắn hơn, nó có thể dễ đọc hơn: bạn chỉ cần học trừu tượng một lần, và sau đó có thể áp dụng nó ở mọi nơi khi đọc mã.

Tôi khuyên bạn nên sử dụng Hoogle để tìm các bộ phối hợp này; khi bạn nghĩ rằng bạn thấy một mẫu chung nằm bên dưới định nghĩa, hãy thử trừu tượng hóa những gì bạn nghĩ là các phần phổ biến, lấy loại kết quả và tìm kiếm nó trên Hoogle. Bạn có thể tìm thấy một combinator mà chỉ là những gì bạn muốn.

Vì vậy, ví dụ, đối với trường hợp mod của bạn, bạn có thể trừu tượng ra alt, năng suất \f (a,b) -> (f a, f b), sau đó tìm kiếm loại của nó, (a -> b) -> (a, a) -> (b, b) - có một kết hợp chính xác, nhưng nó trong thư viện FGL đồ thị, mà bạn không muốn Dựa vào. Tuy nhiên, bạn có thể thấy khả năng tìm kiếm theo loại có thể rất có giá trị thực sự!

Ngoài ra còn có phiên bản dòng lệnh của Hoogle với tích hợp GHCi; xem HaskellWiki page để biết thêm thông tin.

(Ngoài ra còn có Hayoo, những tìm kiếm toàn bộ Hackage, nhưng là hơi ít thông minh với các loại;. Cái nào bạn sử dụng tùy thuộc vào sở thích cá nhân)

4

Đối với một số bản mẫu, Data.Function.on có thể hữu ích, mặc dù trong những ví dụ, nó không đạt được nhiều

instance Ord Foo where 
    (<=) = (<=) `on` modify -- maybe 

mod = uncurry ((,) `on` alt) -- Not really 
Các vấn đề liên quan