2011-08-24 22 views
6

Tôi muốn sáng tác các chức năng theo cách sau:chức năng ngã ba fmap

compose :: (a->b->c) -> (d->a) -> (d->b) -> d -> c 
compose f g h x = f (g x) (h x) 

Vì vậy mà chúng ta có thể sử dụng nó theo cách sau:

compose (==) (myReverse . myReverse) id [1..100] 

Tôi nghĩ rằng nó có thể được đơn giản hóa với một cái gì đó như 'fmap', do đó, nó không cần phải xác định 'soạn' ở tất cả. Nhưng tôi đã không tìm ra cách để làm điều đó.

+0

Điều bạn đã cung cấp là giải pháp đơn giản và dễ đọc nhất. Có thể có khác được gọi là giải pháp mã "dày đặc" cho điều này, nhưng tôi thích mã đơn giản và dễ đọc :) – Ankur

Trả lời

11

Nếu bạn nhập Control.Applicative, sau đó

compose f g h = f <$> g <*> h 

Vì vậy, bạn có thể viết (==) <$> (myReverse . myReverse) <*> id $ [1..100]

<*> chuyên ngành chức năng tương đương với S-combinator:

s f g x = f x (g x) 

Bạn có thể sử dụng Control.Arrow quá :

compose f g h = g &&& h >>> uncurry f 
test = uncurry (==) <<< (myReverse <<< myReverse) &&& id $ [1..100] 

Cập nhật

Tôi đã hỏi lambdabot tại #haskell cùng một câu hỏi và ông đã trả lời đơn giản là liftM2. : D

+0

+1, câu trả lời hay. Là một nửa noob, tôi đã cố gắng để có được cả hai giải pháp bản thân mình, đã rất gần nhưng không làm cho nó (tôi bị mất '<<<' cho sáng tác với 'uncurry'). –

+0

Thực ra '<<<' tương đương với '.'. Đó là '&&&' thực hiện công việc (tách đối số) ở đây. – Rotsor

+1

Tôi biết rằng '<<<' là thành phần, nhưng tôi bị mắc kẹt với 'uncurry (==) ((đảo ngược. Ngược lại) &&& id) $ [1..100] ', mà trong nhận thức là khá ngu ngốc. –

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