함수형 프로그램이 컴파일 성공과 정확성간에 상관 관계가있는 이유는 무엇입니까? 최근에, 나는 순수한 기능적 C # 코드를

LINQ를 처음 사용하기 시작한 이래로 4 년 동안 함수형 프로그래밍을 지향하고 있습니다. 최근에, 나는 순수한 기능적 C # 코드를 작성했고, 기능성 프로그램에 대해 읽은 것을 직접 보았습니다.

나는 이것이 왜 그런지 손가락을 쓰려고했지만 성공하지 못했습니다.

OO 원칙을 적용 할 때 기능 프로그램에없는 “추상 계층”이 있으며이 추상화 계층을 통해 구현 간 잘못된 개체 간 계약을 수정할 수 있습니다.

누구든지 이것에 대해 생각하고 함수형 프로그래밍에서 컴파일 성공과 프로그램 정확성 간의 상관 관계에 대한 근본적인 추상적 이유를 생각해 냈습니까?



답변

나는이 대답을 많은 것을 증명하는 사람으로 쓸 수 있으므로 정확성은 작동하는 것이 아니라 작동하고 입증하기 쉬운 것입니다.

많은 의미에서 함수형 프로그래밍은 명령형 프로그래밍보다 더 제한적입니다. 결국, C에서 변수를 절대로 돌연변이시키는 것을 막을 수있는 것은 없습니다! 실제로 FP 언어의 대부분의 기능은 몇 가지 핵심 기능 측면에서 간단하게 이야기 할 수 있습니다. 그것은 모두 람다, 함수 응용 프로그램 및 패턴 일치로 요약됩니다!

그러나 파이퍼를 미리 지불 했으므로 처리해야 할 일이 훨씬 적고 상황이 어떻게 잘못 될 수 있는지에 대한 옵션이 훨씬 적습니다. 1984 팬이라면 자유는 참으로 노예입니다! 프로그램에 101 가지의 깔끔한 트릭을 사용함으로써 이러한 101 가지 상황이 발생할 수있는 것처럼 사물을 추론해야합니다! 그것이 밝혀지면 정말하기가 어렵습니다 🙂

칼 대신 안전 가위로 시작하면 달리기는 덜 위험합니다.

이제 우리는 당신의 질문을 살펴 봅니다 :이 모든 것이 어떻게 “컴파일하고 작동합니다!” 현상. 나는 이것이 코드를 증명하기 쉬운 이유와 같은 이유라고 생각합니다! 결국, 소프트웨어를 작성할 때 그것이 올바른지에 대한 비공식 증거를 구성하고 있습니다. 이 때문에 당신의 자연적인 손떨림 증거와 컴파일러 자체의 정확성에 대한 개념 (typechecking)은 상당히 많습니다.

기능과 기능 간의 복잡한 상호 작용을 추가하면 유형 시스템에서 확인하지 않는 기능이 증가합니다. 그러나 비공식 증거를 작성하는 능력은 향상되지 않습니다! 즉, 초기 검사를 통해 미끄러질 수있는 것이 많으며 나중에 잡아야합니다.


답변

함수형 프로그래밍에서 컴파일 성공과 프로그램 정확성 간의 상관 관계에 대한 근본적인 추상 이유는 무엇입니까?

가변 상태.

컴파일러는 정적으로 검사합니다. 그것들은 당신의 프로그램이 잘 구성되어 있는지 확인하고 타입 시스템은 올바른 종류의 장소에서 올바른 종류의 값이 허용되도록하는 메커니즘을 제공합니다. 타입 시스템은 또한 올바른 종류의 장소에서 올바른 종류의 의미가 허용되도록 노력합니다.

프로그램이 상태를 도입하자마자 후자의 제약이 덜 유용 해집니다. 올바른 지점에서 올바른 값에 대해 걱정할 필요가있을뿐만 아니라 프로그램의 임의의 지점에서 변경되는 값을 고려해야합니다. 해당 상태와 함께 변경되는 코드의 의미를 고려해야합니다.

함수형 프로그래밍을 잘하고 있다면 변경 가능한 상태가 없거나 아주 적습니다.

컴파일러가 더 많은 버그를 잡을 수 있기 때문에 상태가없는 프로그램이 컴파일 후 더 자주 작동하는 경우 또는 해당 스타일의 프로그래밍으로 버그가 덜 발생하기 때문에 컴파일 후 상태가없는 프로그램이 더 자주 발생하는 경우에는 원인에 대해 약간의 논쟁이 있습니다.

내 경험에 두 가지가 혼합되어있을 것입니다.


답변

간단히 말해서, 제한 사항은 사물을 결합하는 올바른 방법이 적다는 것을 의미하며, 일류 함수는 루프 구조와 같은 요소를 더 쉽게 추출 할 수있게합니다. 이 답변 에서 루프를 가져옵니다. 예를 들면 다음과 같습니다.

for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
    String string = iterator.next();
    if (string.isEmpty()) {
        iterator.remove();
    }
}

이것은 Java에서 반복하는 동안 컬렉션에서 요소를 제거하는 안전한 방법 중 하나입니다. 매우 가깝게 보이지만 잘못된 방법이 많이 있습니다. 이 방법을 모르는 사람들은 때로는 사본을 반복하는 것처럼 문제를 피하기 위해 복잡한 방법을 사용합니다.

이 제네릭을 만드는 것은 끔찍한 일이 아니기 때문에의 컬렉션 이상에서 작동 Strings하지만 일급 함수가 없으면 술어 ( if) 안의 조건을 바꿀 수 없으므로이 코드는 복사되어 붙여 넣는 경향이 있습니다 약간 수정되었습니다.

당신에게주는 일류의 기능을 결합 능력 그렇게하지 않으면 매우 성가신하게 불변성의 제한 매개 변수로의 술어를 통과를, 그리고 당신은 같은 간단한 빌딩 블록 마련 filter이 스칼라 코드와 같이, 그것은 같은 일을합니다 :

list filter (!_.isEmpty)

스칼라의 경우 컴파일 타임에 타입 시스템이 당신을 위해 무엇을 검사하는지 생각해보십시오. 그러나이 검사는 처음으로 그것을 실행할 때 동적 타입 시스템에 의해 수행됩니다.

  • listfilter메소드 를 지원하는 일종의 유형 , 즉 컬렉션 이어야합니다 .
  • 의 요소 에는 부울을 리턴 list하는 isEmpty메소드가 있어야합니다 .
  • 출력은 동일한 유형의 요소를 가진 (잠재적으로) 더 작은 모음입니다.

일단 그러한 것들이 확인되면 프로그래머가 망치는 다른 방법은 무엇입니까? 실수로를 잊어 버렸기 때문에 !테스트 사례가 매우 명백하게 실패했습니다. 그것은 유일하게 할 수있는 유일한 실수이며, 역 조건을 테스트 한 코드에서 직접 번역했기 때문에 실수했습니다.

이 패턴은 반복해서 반복됩니다. 일급 함수를 사용하면 정확한 의미를 가진 재사용 가능한 작은 유틸리티로 사물을 리팩토링 할 수 있으며, 불변성과 같은 제한 사항으로 인해 그렇게 할 수 있습니다. 유틸리티의 매개 변수를 검사하면 유형을 확인하는 데 필요한 공간이 거의 없습니다.

물론 이것은 filter이미 단순화 된 기능이 이미 존재 한다는 것을 알고 그것을 찾을 수 있거나 자신을 만들면 얻을 수있는 이점을 인식 한다는 것을 프로그래머에게 달려 있습니다. 꼬리 재귀 만 사용하여 어디에서나 직접 구현해보십시오. 명령 버전과 같은 복잡한 보트로 돌아 왔습니다. 당신은 그냥 있기 때문에 매우 간단하게 쓰기, 간단한 버전은 분명 의미하지 않는다.


답변

함수형 프로그래밍 컴파일과 런타임 정확성 사이에는 중요한 상관 관계가 없다고 생각합니다. 캐스팅하지 않으면 적어도 올바른 유형을 가질 수 있기 때문에 정적으로 유형이 지정된 컴파일과 런타임 정확성간에 약간의 상관 관계가있을 수 있습니다.

설명과 같이 성공적인 컴파일과 런타임 유형의 정확성을 서로 연관시킬 수있는 프로그래밍 언어 측면은 정적 타이핑이며, 심지어 런타임에만 주장 할 수있는 캐스트로 유형 검사기를 약화하지 않는 경우에만 Java 또는 .Net과 같은 강력한 유형의 값 또는 위치) (타입 정보가 손실되거나 타이핑이 약한 환경 (예 : C 및 C ++))

그러나 기능적 프로그래밍 그 자체는 공유 데이터 및 변경 가능한 상태를 피하는 것과 같은 다른 방법으로 도움이 될 수 있습니다.

두 측면이 모두 정확성과 유의 한 상관 관계를 가질 수 있지만 컴파일 및 런타임 오류가 없으면 프로그램에서 수행해야 할 작업이 빠르게 수행되는 것처럼 광범위한 의미의 정확성에 대해 엄격하게 말하지 않습니다. 잘못된 입력 또는 제어 할 수없는 런타임 오류 이를 위해서는 비즈니스 규칙, 요구 사항, 유스 케이스, 어설 션, 단위 테스트, 통합 테스트 등이 필요합니다. 결국 내 생각에는 기능 프로그래밍, 정적 타이핑 또는 둘 다보다 훨씬 더 자신감이 있습니다.


답변

관리자에 대한 설명 :

기능적 프로그램은 모든 것이 연결되는 하나의 큰 기계, 튜브, 케이블과 같습니다. [차]

절차 적 프로그램은 작은 기계가 들어있는 방이있는 건물과 같은 방식으로 일부 제품을 보관함에 저장하고 다른 곳에서 부분 제품을 가져 오는 것과 같습니다. [공장]

따라서 기능성 기계가 이미 서로 맞으면 무언가를 생산해야합니다. 절차 적 복합체가 실행되면 특정 효과를 감독하고 혼돈을 일으켜 기능을 보장하지 못할 수 있습니다. 모든 것이 올바르게 통합되어 있는지에 대한 점검 목록이 있더라도 상태가 너무 많아서 상황에 따라 (일부 제품이 놓여 있거나 버킷이 넘치거나 누락 됨) 보장하기가 어렵습니다.


그러나 심각하게 절차 코드는 기능 코드만큼 원하는 결과의 의미를 지정하지 않습니다. 절차 적 프로그래머는 상황 코드와 데이터로 더 쉽게 벗어날 수 있으며 한 가지 방법 (일부는 불완전한 방법)을 수행하는 여러 가지 방법을 도입 할 수 있습니다. 일반적으로 외부 데이터가 생성됩니다. 문제가 복잡해지면 기능 프로그래머가 더 오래 걸릴 수 있습니까?

강력한 유형의 기능 언어는 여전히 더 나은 데이터 및 흐름 분석을 수행 할 수 있습니다. 절차 적 언어를 사용하면 프로그램의 목표는 종종 공식 정확성 분석으로 프로그램 외부에서 정의되어야합니다.