함수형 프로그래밍에 대한 다양한 기사를 읽는 동안 ‘Functor’라는 용어를 몇 번 보았지만 저자는 일반적으로 독자가 이미 그 용어를 이해한다고 가정합니다. 웹을 둘러 보면 지나치게 기술적 인 설명 ( Wikipedia 기사 참조 ) 또는 매우 모호한 설명 (이 기관 교육용 웹 사이트의 Functors 섹션 참조 )이 제공되었습니다.
누군가가 용어를 친절하게 정의하고, 그 사용법을 설명하고, 펑터가 어떻게 만들어지고 사용되는지에 대한 예를 제공 할 수 있습니까?
편집 : 나는 용어 뒤에 이론에 관심이 있지만 개념의 구현과 실제 사용에 대한 것보다 이론에 덜 관심이 있습니다.
편집 2 : 몇 가지 교차 용어가 진행되는 것처럼 보입니다. 저는 C ++의 함수 객체가 아닌 함수형 프로그래밍의 Functors를 언급하고 있습니다.
답변
“functor”라는 단어는 범주 이론에서 나왔는데, 이는 매우 일반적이고 매우 추상적 인 수학 분기입니다. 함수형 언어 디자이너는 적어도 두 가지 방법으로 빌려왔다.
-
ML 언어 언어에서 functor는 하나 이상의 다른 모듈을 매개 변수로 사용하는 모듈입니다. 고급 기능으로 간주되며 대부분의 초보 프로그래머에게는 어려움이 있습니다.
구현 및 실제 사용의 예로서, 선호하는 형태의 균형 이진 검색 트리를 한번에 functor로 정의 할 수 있으며, 다음과 같은 기능을 제공하는 모듈로 사용할 수 있습니다.
-
이진 트리에서 사용될 키의 유형
-
키의 총 주문 기능
이 작업을 수행하면 동일한 균형 이진 트리 구현을 영원히 사용할 수 있습니다. (트리에 저장된 값의 유형은 일반적으로 다형성으로 남습니다. 트리는 값을 복사하는 것 이외의 값을 볼 필요가 없지만 트리는 반드시 키를 비교할 수 있어야하며 비교 기능을 가져옵니다. functor의 매개 변수)
ML functors의 또 다른 응용은 계층화 된 네트워크 프로토콜 입니다. CMU Fox 그룹의 링크는 정말 훌륭한 논문입니다. 또한 functors를 사용하여 간단한 계층 유형 (IP 또는 직접 이더넷을 통해)에 더 복잡한 프로토콜 계층 (TCP와 같은)을 구축하는 방법을 보여줍니다. 각 레이어는 그 아래 레이어를 매개 변수로 사용하는 functor로 구현됩니다. 소프트웨어의 구조는 실제로 프로그래머의 마음에만 존재하는 계층과 달리 사람들이 문제에 대해 생각하는 방식을 반영합니다. 이 작품이 출판 된 1994 년에는 큰 일이었습니다.
ML functors의 실제 사례에 대해서는 ML Module Mania 라는 논문 이 있습니다. ML 모듈 시스템 (다른 종류의 모듈과 비교)에 대한 훌륭하고 명료 한 설명은 Xavier Leroy의 화려한 1994 POPL 논문 매니페스트 유형, 모듈 및 개별 컴파일 의 처음 몇 페이지를 읽으십시오 .
-
-
하스켈에서, 일부 관련 순수 함수형 언어에서,
Functor
A는 유형 클래스 . 형식이 특정 동작에 특정 동작을 제공 할 때 형식은 형식 클래스 (또는 기술적으로는 형식 클래스의 인스턴스 임)에 속합니다. 컬렉션과 같은 특정 동작이 있는 유형T
은 클래스에 속할 수 있습니다Functor
.-
유형
T
은 다른 유형에 대해 매개 변수화되며 이는 콜렉션의 요소 유형으로 생각해야합니다. 전체 컬렉션의 유형은 다음과 같이이다T Int
,T String
,T Bool
,는 각각 정수, 문자열 또는 부울을 포함하는 경우. 요소의 형태를 알 수없는 경우, 그것은으로 기록 된 유형 매개 변수a
처럼T a
.예를 들어 목록 (0 개 이상의 유형의 요소
a
),Maybe
유형 (0 또는 하나의 유형a
의 요소), 유형 의 요소 집합a
, 유형 의 요소 배열a
, 유형의 값을 포함하는 모든 종류의 검색 트리a
등이 있습니다. 생각할 수 있습니다. -
T
만족해야 할 또 다른 속성 은 유형a -> b
의 함수 (요소의 함수)가있는 경우 해당 함수를 가져 와서 콜렉션에서 관련 함수를 생성 할 수 있어야한다는 것입니다. 유형 클래스의fmap
모든 유형이 공유 하는 연산자 로이를 수행합니다Functor
. 당신이 함수 그래서 만약 운영자는 실제로 오버로드even
유형을Int -> Bool
한 후,fmap even
많은 훌륭한 일을 할 수있는 오버로드 된 함수입니다 :
-
정수 목록을 부울 목록으로 변환
-
정수 트리를 부울 트리로 변환
-
변환
Nothing
에Nothing
와Just 7
에Just False
Haskell에서이 속성은 다음 유형을 나타냅니다
fmap
.fmap :: (Functor t) => (a -> b) -> t a -> t b
여기서 우리는 작은 클래스를 갖게
t
되었습니다Functor
. “클래스의 모든 유형”을 의미합니다 . -
간단히 이야기하자면, Haskell 에서 functor는 요소에 함수가 제공되면 collections에 함수를 제공하는 일종의
fmap
컬렉션 입니다. 당신이 상상할 수 있듯이, 이것은 널리 재사용 할 수있는 아이디어이므로 하스켈의 표준 라이브러리의 일부로 축복을받습니다. -
평소와 같이 사람들은 새롭고 유용한 추상화를 계속해서 개발하고 있으며, 응용 기능 을 살펴보고 싶을 때 가장 유용한 참고 자료는 Conor McBride와 Ross Paterson의 Applicative Programming with Effects 라는 논문 입니다.
답변
여기에 다른 답변이 완료되었지만 functor 의 FP 사용에 대한 다른 설명을 시도해 보겠습니다 . 이것을 유추로 보자.
펑터 타입의 컨테이너 에서지도하는 기능을 실시한다는 → b는 입력의 산출 컨테이너 B를 .
C ++에서 abstracted function-pointer 사용과 달리 여기서 functor는 함수가 아닙니다 . 오히려, 함수를 받을 때 일관되게 동작 하는 것 입니다.
답변
크게 관련이없는 세 가지 다른 의미가 있습니다!
-
Ocaml에서는 매개 변수화 된 모듈입니다. 매뉴얼을 참조하십시오 . 나는 그것들을 이해하는 가장 좋은 방법은 예를 들면 다음과 같다고 생각합니다. (빠르게 작성하면 버그가있을 수 있습니다)
module type Order = sig type t val compare: t -> t -> bool end;; module Integers = struct type t = int let compare x y = x > y end;; module ReverseOrder = functor (X: Order) -> struct type t = X.t let compare x y = X.compare y x end;; (* We can order reversely *) module K = ReverseOrder (Integers);; Integers.compare 3 4;; (* this is false *) K.compare 3 4;; (* this is true *) module LexicographicOrder = functor (X: Order) -> functor (Y: Order) -> struct type t = X.t * Y.t let compare (a,b) (c,d) = if X.compare a c then true else if X.compare c a then false else Y.compare b d end;; (* compare lexicographically *) module X = LexicographicOrder (Integers) (Integers);; X.compare (2,3) (4,5);; module LinearSearch = functor (X: Order) -> struct type t = X.t array let find x k = 0 (* some boring code *) end;; module BinarySearch = functor (X: Order) -> struct type t = X.t array let find x k = 0 (* some boring code *) end;; (* linear search over arrays of integers *) module LS = LinearSearch (Integers);; LS.find [|1;2;3] 2;; (* binary search over arrays of pairs of integers, sorted lexicographically *) module BS = BinarySearch (LexicographicOrder (Integers) (Integers));; BS.find [|(2,3);(4,5)|] (2,3);;
이제 가능한 많은 주문을 신속하게 추가 할 수 있으며, 새로운 주문을 작성하는 방법, 이진 또는 선형 검색을 쉽게 수행 할 수 있습니다. 일반 프로그래밍 FTW.
-
Haskell과 같은 함수형 프로그래밍 언어에서 “매핑”될 수있는 일부 유형 생성자 (목록, 세트와 같은 매개 변수화 된 유형)를 의미합니다. 정확하게 말하면 펑터에는가
f
장착되어(a -> b) -> (f a -> f b)
있습니다. 이것은 범주 이론의 기원을 가지고 있습니다. 링크 된 Wikipedia 기사가이 사용법입니다.class Functor f where fmap :: (a -> b) -> (f a -> f b) instance Functor [] where -- lists are a functor fmap = map instance Functor Maybe where -- Maybe is option in Haskell fmap f (Just x) = Just (f x) fmap f Nothing = Nothing fmap (+1) [2,3,4] -- this is [3,4,5] fmap (+1) (Just 5) -- this is Just 6 fmap (+1) Nothing -- this is Nothing
그래서 이것은 특별한 종류의 타입 생성자이며 Ocaml의 펑터와는 거의 관련이 없습니다!
- 명령형 언어에서는 함수를 가리키는 포인터입니다.
답변
OCaml에서는 매개 변수화 된 모듈입니다.
C ++을 알고 있다면 OCaml functor를 템플릿으로 생각하십시오. C ++에는 클래스 템플릿 만 있으며 펑 터는 모듈 규모로 작동합니다.
functor의 예는 Map.Make입니다. module StringMap = Map.Make (String);;
문자열 키 맵과 함께 작동하는 맵 모듈을 빌드합니다.
다형성만으로 StringMap과 같은 것을 얻을 수 없었습니다. 키에 대해 몇 가지 가정을해야합니다. 문자열 모듈에는 전체적으로 정렬 된 문자열 유형에 대한 연산 (비교 등)이 포함되며 functor는 문자열 모듈에 포함 된 연산과 연결됩니다. 객체 지향 프로그래밍과 비슷한 것을 할 수는 있지만 메소드 간접 오버 헤드가 있습니다.
답변
당신은 꽤 좋은 답변을 받았습니다. 나는 투구 할 것이다 :
수학적 의미에서 펑 터는 대수에서 특별한 종류의 기능입니다. 대수를 다른 대수에 매핑하는 최소한의 함수입니다. “최소 성”은 functor 법률에 의해 표현됩니다.
이것을 보는 두 가지 방법이 있습니다. 예를 들어,리스트는 어떤 유형의 함수입니다. 즉, ‘a’유형에 대한 대수가 주어지면 ‘a’유형의 항목을 포함하는 호환되는 대수 목록을 생성 할 수 있습니다. (예를 들어, 요소를 포함하는 단일 목록으로 요소를 가져 오는 맵 : f (a) = [a]) 다시, 호환성 개념은 functor 법률에 의해 표현됩니다.
다른 한편으로, 펑터 (functor) f “a”는 타입 a (즉, fa는 펑터 f를 타입 a의 대수에 적용한 결과 임)이며 g에서 함수입니다 : a-> b, 우리는 계산할 수 있습니다 fa에 f를 매핑하는 새로운 functor F = (fmap g) b. 간단히 말해, fmap은 “functor parts”를 “functor parts”에 매핑하는 F의 일부이고 g는 “algebra parts”를 “algebra parts”에 매핑하는 기능의 일부입니다. 함수, functor가 필요하고 일단 완료되면 functor이기도합니다.
다른 언어는 다른 개념의 펑터를 사용하고있는 것처럼 보이지만 그렇지 않습니다. 그들은 단순히 다른 대수에 함수를 사용하고 있습니다. OCamls에는 대수 모듈이 있으며 해당 대수를 통해 함수를 사용하면 새로운 선언을 “호환 가능한”방식으로 모듈에 첨부 할 수 있습니다.
Haskell functor는 타입 클래스가 아닙니다. 유형 클래스를 충족시키는 자유 변수가있는 데이터 유형입니다. 자유 변수가없는 데이터 유형의 내장을 기꺼이 파고 싶다면 데이터 유형을 기본 대수의 함수로 해석 할 수 있습니다. 예를 들면 다음과 같습니다.
데이터 F = F Int
Int 클래스에 동형입니다. 따라서 값 생성자 인 F는 Int를 동등한 대수 인 F Int에 매핑하는 함수입니다. functor입니다. 반면에, 당신은 여기서 무료로 fmap을 얻지 못합니다. 이것이 패턴 일치를위한 것입니다.
펑 터는 대수적으로 요소를 대수적으로 호환되는 방식으로 “첨부”하는 데 유용합니다.
답변
이 질문에 대한 가장 좋은 답변은 Brent Yorgey의 “Typeclassopedia”에 있습니다.
Monad Reader의 이번 호에는 functor가 무엇인지에 대한 정확한 정의와 다른 개념 및 다이어그램에 대한 많은 정의가 포함되어 있습니다. (모노 이드, 어플리 케이 티브, 모나드 및 기타 개념은 펑터와 관련하여 설명되고 보입니다).
http://haskell.org/sitewiki/images/8/85/TMR-Issue13.pdf
Functor 용 Typeclassopedia에서 발췌 : “간단한 직감은 Functor가 컨테이너의 모든 요소에 균일하게 기능을 적용하는 기능과 함께 일종의”컨테이너 “를 나타냅니다.”
그러나 실제로 전체 classclasspedia는 놀랍도록 쉬운 권장 사항입니다. 어떤 식 으로든 주어진 클래스 또는 클래스가 주어진 동작이나 기능에 대한 어휘를 제공한다는 점에서 객체의 디자인 패턴과 평행하게 표시되는 것을 볼 수 있습니다.
건배
답변
O’Reilly OCaml 책에는 Inria의 웹 사이트에있는 좋은 예가 있습니다 (이 글은 불행히도 다운되었습니다). 이 책에서 caltech가 사용한 매우 유사한 예를 찾았습니다 : OCaml 소개 (pdf 링크) . 관련 섹션은 펑터에 관한 장입니다 (도서의 139 페이지, PDF의 149 페이지).
이 책에는 목록으로 구성된 데이터 구조를 작성하고 요소를 추가하고 요소가 목록에 있는지 판별하고 요소를 찾는 기능을하는 MakeSet 기능이 있습니다. 세트에 있는지 여부를 결정하는 데 사용되는 비교 함수가 매개 변수화되었습니다 (이는 MakeSet을 모듈 대신 functor로 만드는 이유입니다).
또한 대소 문자를 구분하지 않는 문자열 비교를 수행하기 위해 비교 기능을 구현하는 모듈이 있습니다.
functor와 비교를 구현하는 모듈을 사용하면 한 줄에 새 모듈을 만들 수 있습니다.
module SSet = MakeSet(StringCaseEqual);;
대소 문자를 구분하지 않는 비교를 사용하는 세트 데이터 구조에 대한 모듈을 작성합니다. 대 / 소문자를 구분하는 비교를 사용하는 집합을 만들려면 새 데이터 구조 모듈 대신 새 비교 모듈을 구현하면됩니다.
Tobu는 functors를 C ++의 템플릿과 비교했는데 꽤 적절하다고 생각합니다.