2011-06-22 69 views
15

Tôi muốn có một hàm để ánh xạ một hàm thuần túy cho một vùng chứa hoặc sắp xếp chuỗi hành động đơn/đơn lẻ thông qua nó. Để lập bản đồ tinh khiết chúng tôi cóFunctor là dành cho (a -> b) -> (f a -> f b), cái gì cho (Danh mục c) => c a b -> c (f a) (f b)?

fmap :: Functor f => (a -> b) -> (f a -> f b) 

Đối với trình tự monadic chúng tôi có (từ Data.Taversable)

mapM :: (Traversable f, Monad m) => (a -> m b) -> (f a -> m (f b)) 

Đó là tương tự như

mapKleisli :: (Traversable f, Monad m) => Kleisli m a b -> Kleisli m (f a) (f b) 
mapKleisli = Kleisli . mapM . runKleisli 

Chúng tôi biết cả hai (->) và (Kleisli m) là các loại (và các mũi tên). Vì vậy, nó là tự nhiên để làm cho một generalisation:

mapCategory :: (X f, Category c) => c a b -> c (f a) (f b) 

Bạn có biết một lớp X với phương pháp tương tự? Có lẽ, ở đâu đó trên hackage? Tôi đã cố gắng để hoogle/hayoo nhưng không tìm thấy bất cứ điều gì thích hợp.

Cập nhật:

Bây giờ tôi biết rõ hơn những gì tôi cần. Cả hai mũi tên Kleisli và (->) đều là các cá thể của ArrowApply mạnh mẽ như Monad. Tôi đã đưa ra phiên bản này mũi tên dựa trên Travesable:

{-# LANGUAGE TypeOperators #-} 

import Prelude hiding (id, (.), mapM) 
import Control.Arrow 
import Control.Category 

class Traversable f where 
    traverse :: ArrowApply (~>) => f a -> (a ~> b) ~> f b 

mapArrow :: (ArrowApply (~>), Traversable f) => a ~> b -> f a ~> f b 
mapArrow a = arr (\x -> (traverse x, a)) >>> app 

instance Traversable Maybe where 
    traverse Nothing = arr (const Nothing) 
    traverse (Just x) = arr (\a -> (a, x)) >>> app >>> arr Just 

instance Traversable [] where 
    traverse [] = arr (const []) 
    traverse (x : xs) = undefined -- this is hard! 

tôi có thể sử dụng chỉ thường applicative dựa trên traversable, đậm đà bản sắc cho các chức năng thuần túy, nhưng tôi không chắc chắn rằng nó là tốt. Xem xét các chức năng thuần túy như trường hợp đặc biệt của các hành động monadic là lạ. Giải thích cả hai hàm thuần túy và các hành động monadic như các cá thể của một số lớp hành động (Category/Arrow/ArrowApply) trông đơn giản hơn với tôi.

Câu hỏi: bạn có muốn hoàn thành bản sao cho [] không? Ý kiến ​​của tôi về ArrowApply vs Monad có ý nghĩa gì không?

Trả lời

10

Bạn đang yêu cầu "một số lớp X", nhưng phải rõ ràng là tên đúng nhất (hoặc có lẽ, chỉ) cho lớp này sẽ là "Functor". Những gì bạn muốn chỉ đơn giản là một lớp functor được định nghĩa cho một cá thể Category tùy ý, thay vì giới hạn ở (->).

Tất nhiên, định nghĩa của bạn vẫn bị giới hạn đối với các thư viện (endo) từ một danh mục đến một danh mục phụ được định nghĩa bởi trình tạo kiểu cho ví dụ. Nếu bạn khái quát một chút nữa, không có lý do cho hai loại là như nhau, đem lại cho bạn a type class something like this one:

class (Category r, Category t) => Functor f r t | f r -> t, f t -> r where 
    fmap :: r a b -> t (f a) (f b) 

này vẫn còn hết sức hạn chế so với các khái niệm đầy đủ của một functor trong lý thuyết thể loại, nhưng cũng oh . Nó cũng thú vị khi quan sát rằng điều này vẫn còn có một constructor loại (->) trong nó - đó là bởi vì, mặc dù chúng tôi đang mô hình hóa các nguồn và mục tiêu với các trường hợp tùy ý, toàn bộ điều (và đặc biệt, chính functor) vẫn tồn tại theo một nghĩa nào đó trong số Hask, tức là danh mục được liên kết với (->). Nửa còn lại của hàm functor (các đối tượng ánh xạ một phần) là, gần như nói, (->) trong loại * -> * cho hàm tạo kiểu f.

+0

Cảm ơn câu trả lời, nhưng trong trường hợp này tôi có nhiều sự quan tâm thực tế hơn lý thuyết. [Trong gói danh mục] (http://hackage.haskell.org/packages/archive/categories/0.56.0/doc/html/Control-Categorical-Functor.html) chúng tôi chỉ có (Endo) Functor trường hợp cho (->) thể loại mà cho chúng ta không có gì mới so với những gì chúng tôi có trong cơ sở (ngoại trừ bản thân lớp). – modular

+0

@ user713303: Bạn được tự do viết các phiên bản của riêng mình. Ví dụ, nó sẽ rất đơn giản để làm như vậy cho các mũi tên Kleisli, như bạn đã thể hiện trong câu hỏi của bạn. –

+1

Trong thực tế, nếu bạn có thực tế và hữu ích trường hợp trong tâm trí, tại sao không đóng góp chúng? Đây là [trang github] (https://github.com/ekmett/categories) cho gói. –

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