2010-03-03 22 views
15

thể trùng lặp:
In Functional Programming, what is a functor?Bạn vui lòng giải thích cho các giáo viên của OCaml không?

Tôi không biết nhiều về OCaml, tôi đã nghiên cứu F # trong một thời gian và khá hiểu nó.

Họ nói rằng F # bỏ qua mô hình functor, hiện diện trong OCaml. Tôi đã cố gắng tìm ra những gì chính xác functor là, nhưng wikipedia và hướng dẫn đã không giúp tôi nhiều.

Bạn có thể làm sáng tỏ bí ẩn đó cho tôi không? Cảm ơn trước :)

CHỈNH SỬA:

Tôi đã hiểu điểm, thx với tất cả những người đã giúp tôi. Bạn có thể đóng câu hỏi là trùng lặp chính xác của: In Functional Programming, what is a functor?

+0

Tôi không phải là F # hay OCaml guru. 't làm điều này như là một câu trả lời chính thức, nhưng tôi nghĩ rằng http://blog.matthewdoig.com/?p=152 có thể giúp bạn ra một chút trong việc giải thích các functors và làm thế nào F # được xung quanh sự vắng mặt của họ. –

+0

Tôi đã đọc bài viết đó trước, cũng có blog.matthewdoig.com/?p=155. Tôi đang ở nửa chừng để hiểu điều đó :) – Bubba88

Trả lời

12

Functors là mô-đun được tham số hóa theo mô-đun, tức là phản ánh từ mô-đun đến mô-đun (hàm bình thường là phản ánh từ giá trị đến giá trị, hàm đa hình phản ánh từ loại này sang hàm bình thường).

Xem thêm ocaml-tutorial on modules.

Examples in the manual cũng hữu ích.

+0

Tôi trễ 10 giây :-) Tôi không phải là chuyên gia và tôi đã hiểu giải thích này. – yogsototh

+2

Đây là giải thích tốt về những gì mà các hàm famtors * là *, và những gì chúng * là tốt cho * là lập trình các cấu trúc dữ liệu chung (xem việc thực hiện Set trong thư viện chuẩn OCaml, nó có lẽ là ví dụ đơn giản nhất của functor) một giải pháp thay thế được kiểm tra kiểu tĩnh, hiệu quả đối với nhiều vấn đề mà bạn cũng có thể giải quyết bằng lập trình hướng đối tượng. –

+0

Ước gì tôi đã may mắn) .. Vì vậy, nếu tôi hiểu nó đúng cách: functors là cách để làm cho các mô-đun mới bằng cách parametrizing hiện có module như 'Set'? – Bubba88

29

Nếu bạn đến từ một vũ trụ OOP, sau đó nó có thể giúp suy nghĩ của một mô-đun tương tự như một lớp tĩnh. Tương tự như các lớp tĩnh .NET, mô-đun OCaml có các hàm tạo; không giống như .NET, các mô-đun OCaml có thể chấp nhận các tham số trong các hàm tạo của chúng. Một hàm functor là một tên đáng sợ cho đối tượng mà bạn truyền vào trong hàm tạo module.

Vì vậy, sử dụng ví dụ kinh điển của một cây nhị phân, chúng tôi thường viết nó trong F # như thế này:

type 'a tree = 
    | Nil 
    | Node of 'a tree * 'a * 'a tree 

module Tree = 
    let rec insert v = function 
     | Nil -> Node(Nil, v, Nil) 
     | Node(l, x, r) -> 
      if v < x then Node(insert v l, x, r) 
      elif v > x then Node(l, x, insert v r) 
      else Node(l, x, r) 

Fine và dandy. Nhưng F # biết cách so sánh hai đối tượng thuộc loại 'a bằng cách sử dụng các toán tử <>?

Đằng sau hậu trường, một cái gì đó làm nó như thế này:

> let gt x y = x > y;; 

val gt : 'a -> 'a -> bool when 'a : comparison 

Alright, cũng những gì nếu bạn có một đối tượng kiểu Person mà không thực hiện mà giao diện cụ thể không? Điều gì sẽ xảy ra nếu bạn muốn xác định chức năng phân loại khi đang di chuyển?Một cách tiếp cận chỉ là để vượt qua trong Comparer như sau:

let rec insert comparer v = function 
     | Nil -> Node(Nil, v, Nil) 
     | Node(l, x, r) -> 
      if comparer v x = 1 then Node(insert v l, x, r) 
      elif comparer v x = -1 then Node(l, x, insert v r) 
      else Node(l, x, r) 

làm việc, nhưng nếu bạn đang viết một module cho các hoạt động cây với chèn, tra cứu, di chuyển, vv, bạn yêu cầu khách hàng để vượt qua trong một chức năng đặt hàng mỗi khi họ gọi bất cứ thứ gì.

Nếu functors F # được hỗ trợ, cú pháp giả của nó có thể trông như thế này:

type 'a Comparer = 
    abstract Gt : 'a -> 'a -> bool 
    abstract Lt : 'a -> 'a -> bool 
    abstract Eq : 'a -> 'a -> bool 

module Tree (comparer : 'a Comparer) = 
    let rec insert v = function 
     | Nil -> Node(Nil, v, Nil) 
     | Node(l, x, r) -> 
      if comparer.Lt v x then Node(insert v l, x, r) 
      elif comparer.Gt v x then Node(l, x, insert v r) 
      else Node(l, x, r) 

Vẫn trong cú pháp giả, bạn muốn tạo module của bạn như vậy:

module PersonTree = Tree (new Comparer<Person> 
    { 
     member this.Lt x y = x.LastName < y.LastName 
     member this.Gt x y = x.LastName > y.LastName 
     member this.Eq x y = x.LastName = y.LastName 
    }) 

let people = PersonTree.insert 1 Nil 

Thật không may, F # doesn 't hỗ trợ functors, vì vậy bạn phải rơi trở lại trên một số cách giải quyết lộn xộn. Đối với kịch bản trên, tôi hầu như luôn luôn lưu trữ "functor" trong cấu trúc dữ liệu của tôi với một số hàm trợ giúp bổ trợ để đảm bảo nó được sao chép chính xác:

type 'a Tree = 
    | Nil of 'a -> 'a -> int 
    | Node of 'a -> 'a -> int * 'a tree * 'a * 'a tree 

module Tree = 
    let comparer = function 
     | Nil(f) -> f 
     | Node(f, _, _, _) -> f 

    let empty f = Nil(f) 

    let make (l, x, r) = 
     let f = comparer l 
     Node(f, l, x, r) 

    let rec insert v = function 
     | Nil(_) -> make(Nil, v, Nil) 
     | Node(f, l, x, r) -> 
      if f v x = -1 then make(insert v l, x, r) 
      elif f v x = 1 then make(l, x, insert v r) 
      else make(l, x, r) 

let people = Tree.empty (function x y -> x.LastName.CompareTo(y.LastName)) 
+4

Cảm ơn bạn về ví dụ hữu ích này. Bạn đã quản lý để làm điều đó mà không có một dòng mã Ocaml, huh)) – Bubba88

+4

Điều này khác với việc chấp nhận một cá thể của IEqualityComparer, ví dụ, trong hàm tạo? Nó có thể được thực hiện ad-hoc bằng cách sử dụng các biểu thức đối tượng. – Daniel

+6

@Daniel: đó là điểm cơ bản. OCaml functor về cơ bản là giống như truyền một số loại đối tượng vào trong một hàm tạo của mô-đun. Nhưng vì F # modules == .NET static classes, và .NET static constructor không chấp nhận tham số trong constructors của chúng, bạn cần phải nhảy qua hoops để có được cùng một loại chức năng. – Juliet

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