2010-03-03 3 views
15

가능한 중복 : 나는 OCaml의에 대해 잘 모르는
In Functional Programming, what is a functor?OCaml 펑터를 설명해 주시겠습니까?

, 나는 몇 시간 동안 F 번호를 공부하고 확실히 이해했습니다.

그들은 F #이 OCaml에있는 functor 모델을 놓쳤다 고합니다. 나는 정확하게 functor가 무엇인지 알아 내려고 노력했지만 wikipedia와 튜토리얼은별로 도움이되지 못했다.

저에게 그 수수께끼를 비추어 주시겠습니까? 미리 감사드립니다 :)

편집 : 나에게 도움이 모든 사람에게

나는 점을 잡았습니다

, 들으. In Functional Programming, what is a functor?

+0

나는 내가 얻었던 F 번호도 OCaml의 전문가가 아니에요 정식 답장으로 이것을하지는 않겠지 만 http://blog.matthewdoig.com/?p=152가 펑터를 설명하는 데 조금 도움이 될 수 있으며 F #이 부재시에 어떻게 발생하는지 생각하고 있습니다. –

+0

그 기사를 먼저 읽었습니다. blog.matthewdoig.com/?p=155도 있습니다. 나는 그 일을 이해하는 중간에있어 :) – Bubba88

답변

12

펑터는 모듈에 의해 매개 변수화 된 모듈입니다 (즉, 함수는 값에서 값으로의 반영이며, 다형 함수는 형식에서 일반 함수로의 반영입니다).

도 참조하십시오. ocaml-tutorial on modules

Examples in the manual도 도움이됩니다.

+0

나는 전문 아니다 십초 늦게 :-) 이었고, 나는이 설명을 이해했다. – yogsototh

+2

이것은 OCaml 펑터 *가 무엇인지에 대한 좋은 설명이며, *에 적합한 *는 일반적인 데이터 구조를 프로그래밍하는 것입니다 (OCaml 표준 라이브러리의 Set 구현을 참조하십시오). 일반적으로 제공하는 가장 간단한 예제입니다. 객체 지향 프로그래밍으로 해결할 수있는 많은 문제에 대한 정적이고 효율적인 유형 확인 대체 솔루션입니다. –

+0

소원 나는 그 것이었다 운이 좋은). 그래서, 나는 그것을 올바르게 이해한다면 : 펑터는'Set'와 같은 기존 모듈을 매개 변수 화하여 새로운 모듈을 만드는 방법입니까? – Bubba88

29

당신이 날 때는 OOP 유니버스라면 모듈을 정적 클래스와 비슷한 것으로 생각하는 것이 도움이 될 것입니다. .NET 정적 클래스와 유사하게, OCaml 모듈은 생성자를가집니다. .NET과 달리 OCaml 모듈은 생성자에서 매개 변수를 받아 들일 수 있습니다. functor는 모듈 생성자에 전달하는 객체의 무서운 울성 이름입니다.

그래서 이진 트리의 정규 예를 사용하여, 우리는 일반적으로 다음과 같이 F 번호에 쓰기 것 :

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) 

벌금과 멋쟁이를. 그러나 F #은 <> 연산자를 사용하여 'a 유형의 두 객체를 비교하는 방법을 어떻게 알고 있습니까? 장면 뒤에

이 같은 그 일을 뭔가 :

> let gt x y = x > y;; 

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

좋아, 그럼 당신이 특정 인터페이스를 구현하지 않는 유형 Person의 객체가 있다면? 즉석에서 정렬 함수를 정의하고 싶다면 어떻게해야할까요?한 가지 방법은 다음과 같이 비교 자에 전달하는 단지입니다 :

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) 

을을 작동하지만, 당신이 등을 삽입, 조회, 제거, 나무 작업을위한 모듈을 작성하는 경우, 당신은 고객이 필요에 전달하는 이 호출 할 때마다 순서 함수가 필요합니다. F 번호가 펑터를 지원하는 경우

, 그 가상의 구문은 다음과 같습니다

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) 

를 여전히 가상의 구문, 당신은 같은 모듈을 만들 것입니다 :

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 

불행하게도, F 번호의 아무튼를 펑터를 지원하지 않으므로 어리석은 해결 방법을 사용해야합니다. 위의 시나리오는, 나는 거의 항상 확인이 주위에 제대로 복사됩니다를 만들기 위해 몇 가지 auxillary 헬퍼 함수 내 데이터 구조에서 "펑"를 저장 할 경우 :

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

이 유용한 예제를 가져 주셔서 감사합니다. 당신은 Ocaml 코드 라인을 사용하지 않고 관리했습니다.)) – Bubba88

+4

예를 들어 생성자에서 IEqualityComparer의 인스턴스를 받아들이는 것과 다른 점은 무엇입니까? 객체 표현식을 사용하여 임시로 구현 될 수 있습니다. – Daniel

+6

@ 대니얼 : 기본적으로 요점입니다. OCaml functor는 기본적으로 일종의 객체를 모듈의 생성자에 전달하는 것과 같습니다. 그러나 F # 모듈 == .NET 정적 클래스 및 .NET 정적 생성자는 생성자에서 매개 변수를 허용하지 않기 때문에 동일한 종류의 기능을 사용하려면 후프를 뛰어 넘어야합니다. – Juliet