함수형 프로그래밍은 객체 지향의 슈퍼 세트입니까? 수학적 기초를 가지고

기능성 프로그래밍이 많을수록 양파의 레이어가 이전 레이어를 모두 포함하는 것처럼 보이는 추가 추상화 레이어를 추가하는 것처럼 느껴집니다.

이것이 사실인지 모르겠습니다. 수년간 함께해온 OOP 원칙을 벗어나고, 캡슐화, 추상화, 상속, 다형성과 같은 기능적 기능을 설명 할 수 있습니까?

우리 모두가 말할 수 있다고 생각합니다. 예, 튜플을 통해 캡슐화되었거나 튜플이 기술적으로 “기능적 프로그래밍”의 사실로 간주됩니까 아니면 언어의 유틸리티입니까?

Haskell이 “인터페이스”요구 사항을 충족 할 수 있지만 방법이 기능적인 사실인지 다시 확신 할 수 없습니까? 펑터가 수학적 기초를 가지고 있다는 사실은 아마도 함수형을 기대할 수있는 확실한 기초라고 생각합니다.

기능적 사고 방식이 OOP의 4 가지 원칙을 어떻게 충족 시키거나 충족시키지 않는지 자세히 설명하십시오.

편집 : 기능적 패러다임과 객체 지향 패러다임의 차이점을 잘 이해하고 있으며 요즘에는 두 가지 모두를 할 수있는 많은 멀티 패러다임 언어가 있음을 알고 있습니다. 나는 정말로 fp (haskell과 같은 순수 주의자라고 생각)가 나열된 4 가지 중 하나를 수행 할 수있는 방법 또는 왜 그것들을 수행 할 수 없는지에 대한 정의를 찾고 있습니다. 즉, “폐쇄로 캡슐화를 수행 할 수 있습니다” (또는이 믿음이 틀린 경우 이유를 설명하십시오).



답변

함수형 프로그래밍은 OOP보다 높은 계층이 아닙니다. 완전히 다른 패러다임입니다. 기능적 스타일 (F #은 정확히이 목적으로 작성 됨)로 OOP를 수행 할 수 있으며 스펙트럼의 다른 쪽 끝에는 객체 방향의 원칙을 명시 적으로 거부하는 Haskell과 같은 것들이 있습니다.

모듈 및 기능을 지원할만큼 고급 언어로 캡슐화 및 추상화를 수행 할 수 있습니다. OO는 캡슐화를위한 특별한 메커니즘을 제공하지만 OO 고유의 것은 아닙니다. OO의 요점은 당신이 언급 한 두 번째 쌍인 상속과 다형성입니다. 이 개념은 공식적으로 Liskov 대체로 알려져 있으며 객체 지향 프로그래밍에 대한 언어 수준의 지원 없이는 얻을 수 없습니다. (예, 경우에 따라 위조하는 것이 가능하지만 OO가 제공하는 많은 이점을 잃게됩니다.)

함수형 프로그래밍은 Liskov 대체에 중점을 두지 않습니다. 추상화 수준을 높이고 “부작용”을 사용하여 변경 가능한 상태 및 루틴의 사용을 최소화하는 데 중점을 둡니다. 이는 기능적 프로그래머가 실제로 무언가를 계산하는 대신 소리를내는 루틴을 만드는 데 사용하는 용어입니다. 무서운. 그러나 다시 말하지만, 이들은 완전히 분리 된 패러다임으로, 프로그래머의 언어와 기술에 따라 함께 사용할 수 있습니다.


답변

다음 직관이 OOP와 FP를 비교하는 데 유용하다는 것을 알았습니다.

FP를 OOP의 상위 집합으로 간주하는 대신 OOP와 FP를 다음과 같은 유사한 기본 계산 모델을 보는 두 가지 대안으로 생각하십시오.

  1. 실행되는 일부 작업
  2. 작업에 대한 일부 입력 인수
  3. 작업 정의에 영향을 줄 수있는 일부 고정 데이터 / 파라미터
  4. 일부 결과 값
  5. 아마도 부작용 일 수 있습니다.

OOP에서 이것은

  1. 실행되는 방법
  2. 메소드의 입력 인수
  3. 멤버 변수 형식의 일부 로컬 데이터를 포함하는 메소드가 호출 된 오브젝트
  4. 메소드의 반환 값 (아마도 void)
  5. 이 방법의 부작용.

FP에서 이것은

  1. 실행되는 폐쇄
  2. 클로저의 입력 인수
  3. 클로저의 캡처 변수
  4. 클로저의 반환 값
  5. 클로저의 부작용 (하스켈과 같은 순수한 언어에서는 매우 통제 된 방식으로 발생).

이 해석을 통해 객체는 로컬이 아닌 동일한 변수 (컬렉션의 모든 클로저에 공통 인 객체의 멤버 변수)를 모두 캡처하는 클로저 컬렉션 ​​(메서드)으로 볼 수 있습니다. 이 관점은 객체 지향 언어에서 클로저가 종종 정확히 하나의 방법으로 객체로 모델링된다는 사실에 의해 뒷받침됩니다.

다른 관점은 객체 지향 뷰가 객체 (데이터)를 중심으로하고 기능적 뷰는 함수 / 클로저 (작업)를 중심으로한다는 사실에서 비롯된 것으로 생각합니다.


답변

OOP의 정의를 요청한 사람에 따라 다릅니다. 5 명에게 물어 보면 6 개의 정의를 얻게 될 것입니다. 위키 백과는 말합니다 :

객체에 대한 합의 정의 또는 이론을 찾으려고 시도한 결과 그다지 성공적이지 않은 것으로 밝혀졌습니다.

따라서 누군가가 매우 명확한 대답을 할 때마다 소금 한 알로 가져 가십시오.

즉, FP 패러다임으로서 OOP의 상위 집합 이라는 좋은 주장이 있습니다 . 특히 객체 지향 프로그래밍이라는 용어에 대한 Alan Kay의 정의는 이 개념과 모순되지 않습니다 (그러나 Kristen Nygaard는 ). Kay가 정말로 염려 한 것은 모든 것이 객체이며 로직은 객체간에 메시지를 전달하여 구현됩니다.

질문에 더 흥미롭게도 클래스와 객체는 함수와 함수에 의해 반환 된 클로저 (한 번에 클래스와 생성자 역할을 함)로 생각할 수 있습니다. 이는 프로토 타입 기반 프로그래밍과 매우 유사하며 실제로 JavaScript를 통해 정확하게 수행 할 수 있습니다.

var cls = function (x) {
    this.y = x;
    this.fun = function () { alert(this.y); };
    return this;
};

var inst = new cls(42);
inst.fun();

(물론 JavaScript는 순수하게 기능적인 프로그래밍에서는 잘못된 값을 변경할 수 있지만 엄격한 OOP 정의에는 필요하지 않습니다.)

더 중요한 질문은 다음과 같습니다. 이것은 OOP 의 의미있는 분류입니까? 함수형 프로그래밍의 하위 집합으로 생각하면 도움이됩니까? 나는 대부분의 경우 그렇지 않다고 생각합니다.


답변

OO와 같은 FP는 잘 정의 된 용어가 아닙니다. 상이하고 상충되는 정의가 다른 학교가 있습니다. 그들이 공통으로 가지고있는 것을 취하면

  • 함수형 프로그래밍은 일급 함수를 사용한 프로그래밍

  • OO 프로그래밍은 동적으로 해결 된 오버로드의 제한된 형식과 결합 된 포함 다형성을 사용 하여 프로그래밍 합니다. (참고 : OO 서클에서 다형성 은 일반적으로 포함 다형성 을 의미하는 것으로 간주되는 반면, FP 학교는 일반적으로 파라 메트릭 다형성을 의미 합니다.)

다른 모든 것은 다른 곳에 존재하거나 어떤 경우에는 존재하지 않습니다.

FP와 OO는 두 가지 추상화 작성 도구입니다. 그들은 각각 자신의 강점과 약점을 가지고 있지만 (예를 들어, 표현 문제에서 다른 선호되는 확장 방향을 가짐), 다른 것보다 본질적으로 더 강력한 것은 없습니다. FP 커널을 통해 OO 시스템을 구축 할 수 있습니다 (CLOS는 그러한 시스템 중 하나임). OO 프레임 워크를 사용하여 퍼스트 클래스 함수를 얻을 수 있습니다 (예 : 람다 함수가 C ++ 11에 정의 된 방식 참조).


답변

아니; OOP는 절차 적 프로그래밍의 상위 집합으로 볼 수 있으며 인스턴스 필드에 표시된 상태를 가지고 있기 때문에 기능적 패러다임과 근본적으로 다릅니다. 기능적 패러다임에서 변수는 원하는 결과를 얻기 위해 상수 데이터에 적용되는 함수입니다.

실제로 함수형 프로그래밍을 OOP의 하위 집합으로 간주 할 수 있습니다. 모든 클래스를 불변으로 만들면 일종의 함수형 프로그래밍이 있다고 생각할 수 있습니다.


답변

대답:

Wikipedia에는 ​​함수 예제 에 대한 훌륭한 기사 가 있습니다. @Konrad Rudolph는 이미 OOP 기사에 대한 링크를 제공했습니다 .

한 패러다임이 다른 패러다임의 수퍼 세트라고 생각하지 않습니다. 그것들은 프로그래밍에 대한 다른 관점이며 일부 문제는 한 관점과 다른 관점에서 더 잘 해결됩니다.

귀하의 질문은 FP 및 OOP의 모든 구현 으로 인해 더욱 복잡합니다 . 각 언어에는 질문에 대한 정답과 관련된 고유 한 특징이 있습니다.

점점 접하는 램 블링 :

나는 스칼라와 같은 언어가 당신에게 두 세계의 최고를 제공하려고한다는 생각을 좋아합니다. 나는 그것이 당신에게도 두 세계의 합병증을 줄 것이라고 걱정합니다.

Java는 OO 언어이지만 버전 7에는 일종의 클로저를 모방하는 데 사용할 수있는 “자원을 사용하여 시도”기능이 추가되었습니다. 여기서는 다른 함수 중간에 로컬 변수 “a”를 업데이트하여 해당 함수에 표시하지 않습니다. 이 경우 다른 함수의 첫 번째 절반은 ClosureTry () 생성자이고 두 번째 절반은 close () 메서드입니다.

public class ClosureTry implements AutoCloseable {

    public static void main(String[] args) {
        int a = 1;
        try(ClosureTry ct = new ClosureTry()) {
            System.out.println("Middle Stuff...");
            a = 2;
        }
        System.out.println("a: " + a);
    }

    public ClosureTry() {
        System.out.println("Start Stuff Goes Here...");
    }

    /** Interface throws exception, but we don't have to. */
    public void close() {
        System.out.println("End Stuff Goes Here...");
    }
}

산출:

Start Stuff Goes Here...
Middle Stuff...
End Stuff Goes Here...
a: 2

이것은 스트림을 열고, 스트림에 쓰고, 확실하게 닫거나, 두 함수를 서로 호출하는 것을 잊지 않는 방식으로 두 함수를 페어링하려는 의도 된 목적에 유용 할 수 있습니다. . 물론 다른 프로그래머가 무언가를 깨뜨리지 않고 try 블록을 제거 할 수있는 것은 매우 새롭고 특이한 일이므로 현재 일종의 반 패턴이지만 흥미로울 수 있습니다.

가장 필수적인 언어로 모든 루프를 재귀로 표현할 수 있습니다. 객체와 변수는 변경할 수 없습니다. 부작용을 최소화하기 위해 Procecures를 작성할 수 있습니다 (컴퓨터에서 진정한 기능을 수행 할 수는 없다고 주장하지만, 실행하는 데 걸리는 시간과 프로세서 / 디스크 / 시스템 리소스는 피할 수없는 부작용입니다). 일부 기능 언어는 모든 객체 지향 작업이 아니라도 많은 기능을 수행 할 수 있습니다. 일부 언어에는 가변 패턴과 같은 특정 패턴을 방지하는 제한 사항 (예 : 변수 업데이트 허용 안 함)이 있지만 상호 배타적 일 필요는 없습니다.

나에게있어 객체 ​​지향 프로그래밍의 가장 유용한 부분은 데이터 숨기기 (캡슐화), 비슷한 개체를 동일하게 다형성 (다형성)하고 해당 데이터에서 함께 작동하는 데이터와 메서드 (객체 / 클래스)를 수집하는 것입니다. 상속은 OOP의 주력 일지 모르지만 나에게는 가장 중요하고 가장 적게 사용되는 부분입니다.

함수형 프로그래밍에서 가장 유용한 부분은 불변성 (변수 대신 토큰 / 값), 함수 (부작용 없음) 및 클로저입니다.

나는 그것이 객체 지향적이라고 생각하지 않지만, 컴퓨터 과학에서 가장 유용한 것 중 하나는 인터페이스를 선언하는 능력이며, 다양한 기능과 데이터가 그 인터페이스를 구현한다는 것입니다. 또한 몇 가지 변경 가능한 데이터 조각을 사용하고 싶습니다. 따라서 모든 프로그램 디자인에서 변경 가능성과 부작용을 제한하려고 시도하더라도 독점적으로 기능적인 언어로는 완전히 편안하지 않습니다.