2010-10-22 29 views
8

Tôi vừa viết chức năng này mà chỉ cần lấy một cặp có giá trị thứ hai là trong một số đơn nguyên, và "kéo monad ra" để trang trải toàn bộ cặp.Chức năng Haskell đơn giản này đã có một cái tên nổi tiếng chưa?

unSndM :: Monad m => (a, m c) -> m (a, c) 
unSndM (x, y) = do y' <- y 
        return (x, y') 

Có cách nào tốt hơn và/hoặc ngắn hơn hoặc không có điểm hoặc thậm chí tiêu chuẩn để diễn đạt điều này không?

Tôi đã có như xa như sau, với -XTupleSections bật ...

unSndM' :: Monad m => (a, m c) -> m (a, c) 
unSndM' (x, y) = y >>= return . (x,) 

Cảm ơn!

+0

Quy tắc của thẻ 'code-golf': http://stackoverflow.com/tags/code-golf/info – Nakilon

+0

Đủ công bằng. Trang web cho phép tôi thêm thẻ mà không nói cho tôi biết có các quy tắc liên quan đến nó. * nhún vai * – gimboland

Trả lời

12

Một điểm nhỏ: nó có thể viết những dòng này chỉ fmap (không >>=) sử dụng, vì vậy bạn thực sự chỉ cần một ví dụ Functor:

unSndM :: (Functor f) => (a, f c) -> f (a, c) 
unSndM (x, y) = fmap ((,) x) y 

Phiên bản này là một chút tổng quát hơn. Để trả lời câu hỏi của bạn về một phiên bản pointfree, chúng tôi chỉ có thể yêu cầu pointfree:

[email protected]% pointfree "unSndM (x, y) = fmap ((,) x) y" 
unSndM = uncurry (fmap . (,)) 

Vì vậy, vâng, một phiên bản thậm chí ngắn hơn là có thể, nhưng cá nhân tôi thấy uncurry một chút khó khăn để đọc và tránh nó trong hầu hết các trường hợp.

Nếu tôi được viết chức năng này trong mã của riêng tôi, tôi có lẽ muốn sử dụng <$> từ Control.Applicative, mà cạo một ký tự:

unSndM :: (Functor f) => (a, f c) -> f (a, c) 
unSndM (x, y) = ((,) x) <$> y 

<$> chỉ là một từ đồng nghĩa với fmap, và tôi thích điều đó nó làm cho thực tế rằng đây là một loại ứng dụng chức năng một chút rõ ràng hơn.

+1

Tupling cũng xảy ra được đặt hàng thuận tiện, cho phép định nghĩa như 'unSmdM = uncurry $ fmap. (,) 'Thật thú vị, loại chức năng này dễ đọc hơn/mô tả hơn cả việc thực hiện :) – Anthony

+1

Tôi đồng ý, nhưng' unSndM (x, y) = (x,) <$> y' là khá gần. –

+0

Ooh, tôi không biết gì về pointfree - cảm ơn! (Tôi đã thử hoogle, tất nhiên.) Một số phiên bản tốt đẹp ở đây, mà không có bất kỳ nhập khẩu bổ sung hoặc sửa đổi thư viện ;-) - cảm ơn bạn. :-) – gimboland

3

Hoogle là bạn của bạn. Nếu một trong các thư viện chuẩn có nó thì một hoogle cho "Monad m => (a, m b) -> m (a,b)" sẽ tìm thấy nó. Lưu ý rằng chức năng vẫn có thể nằm trong gói hackage, nhưng nó thường không đáng để xây dựng thêm cho các chức năng nhỏ như thế này.

+0

"thường không đáng giá thêm xây dựng-dep chỉ cho các chức năng nhỏ như thế này" <- đây là một điều đáng buồn: ( – Fresheyeball

13

Nếu TraversableFoldable trường cho (,) x) là trong thư viện (và tôi cho rằng tôi phải mất một đổ lỗi cho sự vắng mặt của họ) ...

instance Traversable ((,) x) where 
    traverse f (x, y) = (,) x <$> f y 

instance Foldable ((,) x) where 
    foldMap = foldMapDefault 

... sau đó điều này (đôi khi được gọi là 'sức mạnh') sẽ là một chuyên môn của Data.Traversable.sequence.

sequence :: (Traversable t, Monad m) => t (m a) -> m (t a) 

nên

sequence :: (Monad m) => ((,) x) (m a) -> m (((,) x) a) 

ví dụ:

sequence :: (Monad m) => (x, m a) -> m (x, a) 

Trong thực tế, chuỗi không thực sự sử dụng toàn bộ sức mạnh của Monad: Applicative sẽ làm. Hơn nữa, trong trường hợp này, ghép nối với x là tuyến tính, do đó, traverse chỉ có <$> thay vì các kết hợp ngẫu nhiên khác là pure<*> và (như đã được chỉ ra ở nơi khác), bạn chỉ cần m để có cấu trúc functorial.

+1

Âm thanh giống như sự ra đời của một thư viện @ đề xuất với tôi :-) – sclv

+1

Đẹp và chi phí cũng là chuỗi! http://hackage.haskell.org/packages/archive/category-extras/0.53.5/doc/html/src/Control-Functor-Strong.html –

+1

Nội dung đáng kinh ngạc. Tôi biết nó trông đơn giản, đủ để một nhà lý thuyết danh mục phải đặt tên cho nó. :-) – gimboland

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