"Erik Meijer: 함수형 프로그래밍"에 대한 참고 사항

7896 단어 haskellfunctionaljava
함수형 프로그래밍에 대해 이야기하는 Erik Meijer의 인터뷰에 대한 내 메모: .

매우 흥미로운 인터뷰입니다. Erik은 매우 명료하고 지나치게 이론적이지 않으면서 문제의 핵심을 바로 이해합니다. 다음은 비디오에 대한 내 메모 중 일부입니다.

12:50 - 자바는 타입 서명에 대해 부정직합니다. 예를 들어 int f()f가 호출될 때마다 동일한 int를 반환하는지 또는 백그라운드에서 어떤 작업을 수행하는지 여부를 알려주지 않습니다. 예를 들어 다음 기능을 살펴보십시오.

public class Example {
  int f(int x) {
    return x + 5;
  }

  int g(int x) {
    return x + new Random().nextInt();
  }
}


구현을 보지 않고는 g가 호출될 때마다 변경된다는 것을 알 방법이 없습니다.

다음은 int를 반환하지만 실제로는 int를 반환하지 않는다는 또 다른 예입니다.

  int h(int x) {
    throw new RuntimeException("not an int!");
  }


이것이 왜 문제가 되는가? 다음 예제에서 코드 작업을 하고 있다고 상상해 보십시오. 일부 중복 작업이 진행 중임을 알아차리고 리팩토링하고 싶을 수 있습니다.

  int example() {
    return g(5) + g(5);
  }


따라서 반복되는 코드를 리팩토링하고 다음을 얻습니다.

  int example() {
    int g5 = g(5);
    return g5 + g5;
  }


엄청난! 더 이상 g(5)를 두 번 계산하지 않으므로 함수가 두 배 빠르게 실행됩니다! 불행히도 배후에서g 전역 상태에 액세스하고 있기 때문에 더 이상 정확하지 않습니다. Random의 생성자 내부에는 호출될 때마다 변경되는 난수 생성기를 초기화하기 위해 OS 시계에 대한 호출이 있습니다.

이것은 상당히 인위적인 예이지만 실제 문제를 보여줍니다. 구현에 부작용이 있는지 먼저 확인하지 않고 리팩토링하는 것은 안전하지 않습니다.

16:50 - FP는 수학 함수로 프로그래밍합니다. 함수가 동일한 입력으로 실행될 때마다 항상 동일한 결과를 얻습니다.

27:34 몇 가지 예가 더 있습니다. Ticks라는 변수에 현재 시간이 저장되어 있다고 가정합니다.

static long Ticks // the current time


다음 기능 스타일 코드를 작성하면 Ticks가 부작용이 있으므로 쌍(x,x)을 반환하는 것이 (Ticks, Ticks)를 반환하는 것과 같지 않다는 이전 문제를 보여줍니다.

let x = Ticks // not a valid refactoring
in (x, x)


대신 x를 람다로 바꾸고 두 번 호출하는 곳에서 다음을 수행한다고 가정합니다.

let x = () => Ticks
in (x(), x())


다음과 같은 리팩토링을 수행하고 시작한 곳으로 바로 돌아갈 수 있다는 점을 제외하고는 문제가 해결된 것 같습니다.

let x = () => Ticks
let y = x
in (y, y)


실제로 우리에게 필요한 것은 문제의 순차적인 특성을 모델링하는 방법입니다. Ticks 값이 필요하고 다시 Ticks 값이 필요합니다.

"세계의 상태"를 나타내는 w가 있고 세계의 상태를 취하고 x와 세계의 상태를 포함하는 쌍을 반환하는 람다를 Ticks 만든다고 가정해 보겠습니다.

let x = w => (Ticks, w)


우리는 이것을 다음과 같이 부를 수 있습니다. 세계의 현재 상태를 입력하고 업데이트된 상태를 다시 가져옵니다.

f(w) {
  (t, w') = x(w)
  (t', w'') = x(w')
  (t, t')
}


우리가 여기서 성취하려는 것은 세계의 상태wx로 들어가고 새로운 세계의 상태w'로 나오는 일종의 "스레딩"입니다. 다시 스레드를 통해 w'' 를 얻습니다. 이제 tt'Ticks 의 다른 값이어야 하도록 이 순차적 종속성을 명시적으로 만들었습니다.

하스켈은 다음과 같이 생각할 수 있습니다. 다음 기능이 있다고 상상해보십시오.

 A,       W       ------------>   R,     W'

some   state of     function     result  new state
value  the world                         of the world


이것을 다음과 같이 다시 쓸 수 있습니다.

A -> W -> R, W'


이것을 약간 다르게 괄호로 묶는 것은 인수를 취하고 세계를 취하고 결과와 세계의 상태를 반환하는 함수를 반환하는 함수를 제공합니다.

A -> (W -> R, W')


이제 IO라는 유형 뒤에 이 "세계 상태"에 대한 세부 정보를 숨깁니다.

A -> IO R


결론



나는 여기에서 많은 세부 사항을 훑어 보았고 그 중 일부는 비디오에서 꽤 손으로 흔들었지만 Monads가 존재하는 이유 (시퀀싱)와 측면으로 계산하는 것이 좋은 이유를 구축하고 직관하는 데 정말 도움이 된다고 생각합니다. -효과 명시적.

좋은 웹페이지 즐겨찾기