태그 보관물: haskell

haskell

상태 저장 라이브러리 위에 부작용이없는 인터페이스 대해 말할 다음이있다

에서 존 휴즈와의 인터뷰 그가 얼랑 및 하스켈에 대해 이야기 그는 얼랑의 상태 라이브러리를 사용하는 방법에 대해 말할 다음이있다 :

상태 저장 라이브러리를 사용하려면 일반적으로 부작용이없는 인터페이스를 빌드하여 나머지 코드에서 안전하게 사용할 수 있습니다.

그는 이것이 무엇을 의미합니까? 나는 이것이 어떻게 보일지에 대한 예를 생각하려고 노력하고 있지만 나의 상상력과 지식이 나에게 실패하고 있습니다.



답변

(나는 Erlang을 모르고 Haskell을 쓸 수 없지만 그럼에도 불구하고 대답 할 수 있다고 생각합니다)

이 인터뷰에서 난수 생성 라이브러리의 예가 제공됩니다. 가능한 상태 저장 인터페이스는 다음과 같습니다.

# create a new RNG
var rng = RNG(seed)

# every time we call the next(ceil) method, we get a new random number
print rng.next(10)
print rng.next(10)
print rng.next(10)

출력이 될 수 있습니다 5 2 7. 불변성을 좋아하는 사람에게는 이것이 잘못입니다! 5 5 5동일한 객체에서 메소드를 호출했기 때문에 이어야 합니다.

그렇다면 상태 비 저장 인터페이스는 무엇입니까? 난수 시퀀스를 지연 평가 된 목록으로 볼 수 있습니다. 여기서 next실제로 헤드를 검색합니다.

let rng = RNG(seed)
let n : rng = rng in
  print n
  let n : rng = rng in
    print n
    let n : rng in
      print n

이러한 인터페이스를 사용하면 언제든지 이전 상태로 되돌릴 수 있습니다. 코드의 두 조각이 동일한 RNG를 참조하면 실제로 동일한 숫자 시퀀스를 얻습니다. 기능적인 사고 방식에서 이것은 매우 바람직합니다.

상태 저장 언어로 이것을 구현하는 것은 그렇게 복잡하지 않습니다. 예를 들면 다음과 같습니다.

import scala.util.Random
import scala.collection.immutable.LinearSeq

class StatelessRNG (private val statefulRNG: Random, bound: Int) extends LinearSeq[Int] {
  private lazy val next = (statefulRNG.nextInt(bound), new StatelessRNG(statefulRNG, bound))

  // the rest is just there to satisfy the LinearSeq trait
  override def head = next._1
  override def tail = next._2
  override def isEmpty = false
  override def apply(i: Int): Int = throw new UnsupportedOperationException()
  override def length = throw new UnsupportedOperationException()
}

// print out three nums
val rng = new StatelessRNG(new Random(), 10)
rng.take(3) foreach (n => println(n))

일단 목록처럼 느껴지도록 약간의 구문 설탕을 추가하면 실제로는 아주 좋습니다.


답변

여기서 핵심 개념은 외부 변경 가능 상태 의 개념 입니다. 외부 변경 가능 상태가없는 라이브러리는 부작용이없는 라이브러리입니다. 이러한 라이브러리의 모든 함수는 전달 된 인수에만 의존합니다.

  • 함수가 작성하지 않은 (예 : 매개 변수로) 자원에 액세스하는 경우 외부 상태에 따라 다릅니다 .
  • 함수가 호출자에게 전달되지 않고 파괴하지 않는 것을 생성하면 함수는 외부 상태를 생성합니다.
  • 위에서 외부 상태가 다른 시간에 다른 값을 가질 수 있으면 변경 가능 합니다.

내가 사용하는 편리한 리트머스 테스트 :

  • 기능 A가 기능 B보다 먼저 실행되어야하는 경우 A는 B가 의존하는 외부 상태를 작성합니다.
  • 쓰고있는 함수를 메모 할 수 없으면 외부 변경 가능 상태에 따라 달라집니다. (메모리 부족으로 인해 메모 화는 좋은 생각이 아니지만 여전히 가능해야합니다.)

답변