2015-09-30 28 views
14

Tôi đã chơi xung quanh với một chức năng đơn giản cho người khác Stack Overflow câu hỏi, và viết biểu thức (với applicative ((>) t), có lẽ?):Loại bỏ trùng lặp -

f a x ++ f a y 

Rõ ràng đây là cách tốt nhất để viết biểu thức đó trong cuộc sống thực, dù tôi có tất cả các biến đó trong phạm vi, nhưng tôi thấy sự trùng lặp của f a và nghĩ "Này, có thể bạn có thể loại bỏ điều đó bằng cá thể Ứng dụng cho các hàm". Tôi làm quen với:

liftA2 (++) (flip f x) (flip f y) a 

điều đó thật khủng khiếp. Rõ ràng tôi cũng có thể loại bỏ sự trùng lặp bằng cách ràng buộc f a với một điều gì đó trong mệnh đề where, nhưng điều này được dự định là một bài tập trong việc sử dụng các hàm dựng sẵn.

Trả lời

21

Bạn có thể làm

((++) `on` f a) x y 

Điều đó không sử dụng Applicative, mặc dù (xin lỗi).

+0

Tôi thích câu trả lời này, Tuy nhiên! Tôi đoán tôi đã không thực sự tìm kiếm câu trả lời áp dụng cụ thể, rất nhiều cách để sử dụng thư viện chuẩn để loại bỏ các bản sao. – amalloy

21

[...] có thể bạn có thể loại bỏ điều đó bằng cá thể áp dụng cho hàm.

Bạn có phải sử dụng trường hợp Applicative của ((->) t) không? Nếu bạn chỉ muốn loại bỏ các trùng lặp f a, tại sao không sử dụng danh sách đơn lẻ, thay vào đó?

[x, y] >>= f a 

hay tương đương,

f a =<< [x, y] 

Ví dụ:

λ> let f :: Int -> Int -> [Int]; f a x = [a .. x] 

λ> f 1 2 ++ f 1 3 
[1,2,1,2,3] 

λ> [2, 3] >>= f 1 
[1,2,1,2,3] 

λ> f 1 =<< [2, 3] 
[1,2,1,2,3] 
+0

Điều đáng chú ý là '= <<' giống với 'concatMap' trong tình huống này, vì vậy nếu bạn muốn suy nghĩ về điều này trong danh sách các thao tác thay vì monads, đó là chức năng sử dụng. –

+0

@ cool_me5000 Chắc chắn, nhưng tôi muốn nhấn mạnh khía cạnh monadic của hoạt động. – Jubobs

14

Bikeshedding là thú vị! Một lựa chọn khác là sử dụng các ví dụ Monoid cho các chức năng:

(($x) <> ($y)) (f a) 
+1

Tôi không hiểu điều này. Không phải là thành phần 'mappend', cho các chức năng? Và điều gì đã xảy ra với '++ '? – amalloy

+0

@amalloy Đối với các hàm, 'mappend' được thêm vào theo chiều kim đồng hồ:' mappend f g x = mappend (f x) (g x) '. '(++)' biến mất vì nó là 'mappend' xảy ra tại mỗi điểm. –

3

Kể từ khi câu hỏi ám chỉ một giải pháp sử dụng applicative (mặc dù câu trả lời khác là tao nhã hơn) ...

((++) <$> ($ x) <*> ($ y)) (f a) 
+0

Nếu bạn muốn loại bỏ một số dấu ngoặc đơn, bạn có thể viết: '(++) <$> ($ x) <*> ($ y) $ f a'. – Jubobs

+1

@Jubobs Tôi không chắc liệu anh ấy có đúng hay không, nhưng tôi đã quyết định thử nghiệm đường của Gabriel Gonzalez về việc làm cho mã Haskell dễ đọc hơn đối với những người không phải là người Haskeller: http://www.haskellforall.com/2015/09 /how-to-make-your-haskell-code-more.html. Tránh '($)' là đề xuất hàng đầu của anh ta. – frasertweedale

+0

Cảm ơn bạn đã liên kết ':)' – Jubobs

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