2017-02-27 12 views
9

Tôi đã cố gắng tìm ra cách để làm điều gì đó dọc theo dòng củaCó thể mất một danh sách các hàm và trả về một chức năng mà là tổng hợp

compositeFunctions :: [(a -> a)] -> (a -> a) 

Tôi đã suy nghĩ của họ, tôi có thể sử dụng foldr liên tục gấp danh sách các chức năng trên, nhưng tôi không thể tìm ra bất cứ điều gì.

+7

Bạn đang đi đúng hướng! xem xét 'foldr :: (x -> y -> x) -> x -> [y] -> x', bây giờ thay thế' a -> a' cho 'y'. 'X' cần phải là gì? Giá trị mặc định tốt cho tham số kiểu 'x' là gì? Giá trị của loại 'x -> y -> x' cần phải làm gì? – rampion

+1

'foldMap' (như trong' compositeFunctions = appEndo. FoldMap Endo') chuyển tải _intent_ tốt hơn 'foldr' tôi nghĩ. (Và chỉ một số ít ký tự dài hơn 'foldr (.) Id') – Alec

+0

Sử dụng' foldMap' rất tối nghĩa, imo. – augustss

Trả lời

11

foldr thực hiện chính xác những gì bạn muốn, vì id là bản sắc cho (.) (ví dụ, f . id == f):

compose :: [(a -> a)] -> a -> a 
compose = foldr (.) id 

Trong một hình thức đệ quy rõ ràng hơn:

compose' [] = id 
compose' (f:fs) = f . compose' fs 
8

Chức năng của các hình thức a -> a , tức là đối số và kết quả có cùng loại, được gọi là endomorphisms. Một điều thực sự thú vị về endomorphisms cho một a nhất định là chúng tạo thành một monoid với id làm nhận dạng và (.) làm toán tử. Điều này có nghĩa rằng mconcat nên làm chính xác những gì bạn muốn ...

compositeFunctions = mconcat 

... tiếc là nó hơi phức tạp hơn. Để có được tại Monoid Ví dụ, bạn sẽ phải quấn chức năng của bạn trong Endo Newtype từ Data.Monoid và sau đó unwrap kết quả:

compositeFunctions = appEndo . mconcat . fmap Endo 
+4

Hoặc ngắn gọn hơn 'compositeFunctions = appEndo. foldMap Endo', như tôi đã đề cập trong bình luận của tôi. – Alec

+0

Bạn cũng có thể sử dụng gói bộ giảm tốc, nó sẽ trở thành một cái gì đó như 'reduceWith appEndo'. – mb14

+1

Tại sao không '(a -> a)' chỉ có một cá thể Monoid? Tại sao sử dụng loại mới cần thiết? – amalloy

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