2016-06-20 13 views
5

Chúng tôi biết rằng mọi loại chung chung F[_] với phương pháp map, tuân thủ một số laws, là functor. Ví dụ: List[_], Option[_]F[A] = Env => A là các functors. Tôi chỉ tự hỏi nếu trừu tượng functor này có ý nghĩa.Functors hữu ích như thế nào?

Làm cách nào để tôi có thể sử dụng thực tế là họ là những người yêu thích? Bạn có thể cho thấy một ví dụ về tính toán không tầm thường, mà sẽ sử dụng map và thực sự hữu ích?

+1

Kiểm tra http://www.cis.upenn.edu/~cis194/spring13/lectures/09-functors.html –

+0

Ngoài ra http://eed3si9n.com/learning-scalaz/Functor.html Bạn nghĩ gì tính toán không tầm thường? –

+2

Tôi nghĩ một số người hiểu sai câu hỏi của Michael. Tôi đọc nó như thế này: anh ta hiểu rằng các functors trừu tượng hóa các phương thức 'map()' của nhiều kiểu dữ liệu khác nhau, nhưng anh ta có một thời gian khó hiểu làm thế nào để * sử dụng * thực tế đó. Thật dễ dàng để nghĩ về các ngữ cảnh trong đó * các kiểu cụ thể * là các hàm functors sẽ xuất hiện và đó là lý do tại sao bạn muốn * các loại '* 'map()' đó trong các ngữ cảnh đó. Sẽ khó hơn khi nghĩ về các bối cảnh mà bạn muốn sử dụng một biến * kiểu * bị giới hạn trong 'Functor' nhưng không có ràng buộc nào khác! –

Trả lời

8

Một trong những lợi ích lớn nhất của khái niệm như chức năng là có công trình xây dựng chung cho phép bạn xây dựng các loại phức tạp hơn ra khỏi functors đơn giản hơn, và đảm bảo rằng các các loại phức tạp có các thuộc tính nhất định. Functors dễ hiểu dường như vô nghĩa khi bạn xem xét chúng trong sự cô lập như bạn đã làm, nhưng họ trở nên hữu ích hơn và nhiều hơn nữa các công trình xây dựng như vậy bạn học và làm chủ.

Một trong những ví dụ đơn giản hơn là một số cách kết hợp các functors cũng mang lại một hàm functor; ví dụ, nếu List[A]Option[A] là functors, vì vậy là:

  • Thành phần functors:List[Option[A]]Option[List[A]]
  • Sản phẩm của functors:(List[A], Option[A])
  • Khoản functors:Either[List[A], Option[A]]

Tôi không kno w đủ để viết những dòng này ra tại Scala, nhưng trong thực tế Haskell như những dịch thành mã chung chung như những ví dụ:

-- A generic type to represent the composition of any two functors 
-- `f` and `g`. 
newtype Compose f g a = Compose { getCompose :: f (g a) } 

-- If `f` and `g` are functors, so is `Compose f g`. 
instance (Functor f, Functor g) => Functor (Compose f g) where 
    fmap f (Compose fga) = Compose (fmap (fmap f) fga) 

Đây là một ví dụ rất đơn giản, nhưng:

  • Nó đã hữu ích như là một Công cụ phân tích ít nhất là. A lot của các kiểu dữ liệu mà mọi người viết trong thực tế, khi bạn nhìn vào chúng thông qua ống kính của ví dụ này, hóa ra là sản phẩm, khoản tiền hoặc tác phẩm của các functors đơn giản hơn. Vì vậy, một khi bạn hiểu những công trình này, bạn có thể tự động "cảm nhận" khi bạn viết một loại phức tạp mà nó là một functor, và làm thế nào để viết hoạt động map() của nó.
  • Các ví dụ phức tạp hơn có hương vị giống nhau:
    • Chúng tôi có một chung xây dựng mà đảm bảo hợp đồng nhất định khi khởi tạo với một loại mà thực hiện Functor;
    • Khi chúng tôi thêm Functor triển khai vào bất kỳ loại nào, chúng tôi có khả năng sử dụng loại đó trong cấu trúc đó.

Một ví dụ phức tạp hơn là free monads (liên kết có một Scala ví dụ mở rộng), một công trình thông dịch chung mà dựa vào người dùng cung cấp Functor s để xác định "hướng dẫn" cho ngôn ngữ. Các liên kết khác (và đây là những chủ yếu là trực tiếp từ một tìm kiếm Google):

+0

Cảm ơn bạn, Luis. Rất thú vị thực sự. Bạn có thể đưa ra một ví dụ về một tính toán chỉ sử dụng một 'Functor' (ngoài các monads miễn phí)? – Michael

1

Vâng, một khi bạn biết điều gì đó là một functor, bạn không chỉ nhận được map, bạn sẽ có được tất cả các chức năng bạn có thể lấy được với nó quá

Ví dụ, nó có thể lấy được các chức năng lift trong một cách mà làm việc cho bất kỳ functor.

Lift sẽ "nâng đỡ" một hàm A => B-F[A] => F[B] đối với một số functor F[_] và được định nghĩa là

def lift[A, B](f: A => B): F[A] => F[B] = map(_)(f) 

Nếu bạn đang sử dụng một thư viện như cats hoặc scalaz sau đó bạn sẽ có được những chức năng miễn phí. Các cats documentation có một vài ví dụ khác mà bạn có thể quan tâm

+2

Tôi không đồng ý, nhưng tôi không chắc điều này có thực sự trả lời câu hỏi không. Theo kinh nghiệm của tôi, hiếm khi chỉ có một ràng buộc 'Functor' trong mã ứng dụng - nếu tất cả những gì bạn biết là' F' là một hàm, thì bạn phải có chữ ký giống như 'F [A] = > F [B] ', và tại thời điểm đó, bạn chỉ cần xác định một' A => B' và ánh xạ tại trang gọi, trong đó 'F' thường là bê tông hoặc có các sự kiện khác được biết về nó. –

6

Tôi không biết Scala, nhưng trong Haskell, lớp Functor là điều cần thiết để xác định Van Laarhoven-style lenses :

type Lens' s a = forall f . Functor f => (a -> f a) -> s -> f s 

Các ống kính này thường được định nghĩa cho các loại liên quan cụ thể sa, nhưng điều quan trọng đối với tiện ích của chúng là chúng hoạt động với một hàm functor tùy ý.

Functor cũng đóng vai trò quan trọng trong vai trò là siêu lớp của Applicative và của Traversable. Khi làm việc với các trừu tượng mạnh mẽ hơn này, thường rất hữu ích khi tiếp cận phương thức fmap.

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