문제

나는 하스켈 코드에서 이런 패턴을 자주 발견한다:

options :: MVar OptionRecord
options = unsafePerformIO $ newEmptyMVar

...

doSomething :: Foo -> Bar
doSomething = unsafePerformIO $ do
  opt <- readMVar options
  doSomething' where ...

기본적으로 프로그램 시작 시 초기에 설정되는 옵션이나 이와 유사한 기록이 있습니다.프로그래머는 게으르기 때문에 options 프로그램 전체를 녹음하세요.그는 정의합니다 MVar 그것을 유지하기 위해 - 추악한 사용으로 정의 unsafePerformIO.프로그래머는 상태가 작업이 발생하기 전에 한 번만 설정되도록 보장합니다.이제 프로그램의 각 부분에서 다음을 사용해야 합니다. unsafePerformIO 다시 말하지만, 옵션을 추출하기 위한 것입니다.

내 생각에는 그런 변수가 고려된다. 실용적으로 순수 (나를 때리지 마세요).이 개념을 추상화하고 변수가 한 번만 설정되도록 보장하는 라이브러리가 있습니까?초기화 전에는 호출이 수행되지 않으며 쓸 필요도 없습니다. unsafeFireZeMissilesAndMakeYourCodeUglyAnd DisgustingBecauseOfThisLongFunctionName

도움이 되었습니까?

해결책

설정 유지나 이와 유사한 용도로 MVar를 사용하고 있다면 리더 모나드를 사용해 보는 것은 어떨까요?

foo :: ReaderT OptionRecord IO ()
foo = do
    options <- ask
    fireMissiles

main = runReaderT foo (OptionRecord "foo")

(IO가 필요하지 않은 경우 일반 리더 :P)

다른 팁

약간의 일시적인 편의를 위해 필수 참조 투명성을 거래하는 사람들은 순결이나 편의성이 없습니다.

이것은 나쁜 생각입니다.이 내용이 포함된 코드는 잘못된 코드입니다.*

이 패턴은 안전한 패턴이 아니기 때문에 안전하게 완전히 마무리할 수 있는 방법이 없습니다.코드에서는 이 작업을 수행하지 마세요.이를 수행하는 안전한 방법을 찾지 마십시오.이를 수행하는 안전한 방법은 없습니다.넣어 unsafePerformIO 바닥에 내려놓고 천천히 콘솔에서 뒤로 물러납니다.

*사람들이 최상위 MVar를 사용하는 타당한 이유가 있지만 이러한 이유는 대부분 외부 코드에 대한 바인딩과 관련이 있거나 대안이 매우 지저분한 몇 가지 다른 것들과 관련이 있습니다.그러나 이러한 경우, 내가 아는 한 최상위 MVar는 다음과 같습니다. ~ 아니다 뒤에서 접근 unsafePerformIO.

암시적 매개변수를 사용합니다.모든 기능을 갖추는 것보다 약간 덜 무겁습니다. Reader 또는 ReaderT 그 유형에.함수의 유형 서명을 변경해야 하지만 그러한 변경은 스크립트로 작성할 수 있다고 생각합니다.(Haskell IDE에 좋은 기능이 될 것입니다.)

이 패턴을 사용하지 않는 중요한 이유가 있습니다.내가 아는 한,

options :: MVar OptionRecord
options = unsafePerformIO $ newEmptyMVar

Haskell은 다음을 보장하지 않습니다. options 한 번만 평가됩니다.의 결과 이후 option 순수한 값이므로 메모하여 재사용할 수 있지만 모든 호출에 대해 다시 계산할 수도 있습니다(예:인라인됨) 프로그램의 의미는 변경되어서는 안 됩니다(귀하의 경우와는 반대로).

그래도 이 패턴을 사용하기로 결정했다면, 꼭 추가하세요 {-# NOINLINE options #-}, 그렇지 않으면 인라인화되어 프로그램이 실패할 수 있습니다!(그리고 이로 인해 우리는 언어와 유형 시스템이 제공하는 보장에서 벗어나 특정 컴파일러의 구현에만 의존하게 됩니다.)

이 주제는 널리 논의되었으며 가능한 해결책은 Haskell Wiki에 잘 요약되어 있습니다. 최상위 변경 가능 상태.현재 추가적인 컴파일러 지원 없이는 이 패턴을 안전하게 추상화하는 것이 불가능합니다.

나는 하스켈 코드에서 이런 패턴을 자주 발견한다:

다른 코드를 읽어보세요.

프로그래머는 게으르기 때문에 프로그램 전체에 옵션 레코드를 가지고 다니기를 원하지 않습니다.그는 unsafePerformIO를 추악하게 사용하여 이를 유지하기 위해 MVar를 정의합니다.프로그래머는 상태가 작업이 발생하기 전에 한 번만 설정되도록 보장합니다.이제 프로그램의 각 부분은 옵션을 추출하기 위해 다시 unsafePerformIO를 사용해야 합니다.

리더 모나드가 안전한 방식으로 수행한다는 점을 제외하면 문자 그대로 리더 모나드가 수행하는 작업과 정확히 일치하는 것 같습니다.자신의 게으름을 수용하는 대신 실제로 좋은 코드를 작성하십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top