이것은 IO
모나드 의 제안 된 "통역"입니다 . 이 "통역"을 진지하게 받아들이려면 "RealWorld"를 진지하게 고려해야합니다. action world
추론 적으로 평가 되는지 action
, 부작용이 없는지, 영향이있을 경우, 그 영향이 발생한 우주의 새로운 상태 (예 : 네트워크 패킷이 전송 된)를 반환함으로써 그 영향을 처리 하는지 여부 는 관련 이 없습니다. 그러나 함수의 결과 ((),world)
는 우주의 새로운 상태입니다 world
. 우리는 측면에서 추측 적으로 평가했을 수있는 새로운 우주를 사용하지 않습니다. 우주의 상태는 world
입니다.
당신은 아마 그것을 심각하게 받아들이는 데 어려움을 겪을 것입니다. 이것이 가장 피상적으로 역설적이고 무의미한 방법은 여러 가지가 있습니다. 동시성은 특히이 관점에서 명백하지 않거나 미쳤습니다.
"잠깐만 요."라고 말합니다. " RealWorld
는 단지 '토큰'입니다. 실제로 전체 우주의 상태가 아닙니다 ." 자,이 "통역"은 아무 것도 설명하지 않습니다. 그럼에도 불구하고, 구현 세부 사항 으로서 , 이것이 GHC 모델 IO
입니다. 1 그러나 이것은 실제로 부작용이있는 마법의 "기능"을 가지고 있으며이 모델은 그 의미에 대한 지침을 제공하지 않음을 의미합니다. 그리고 이러한 기능에는 실제로 부작용이 있기 때문에 제기하는 관심사는 완전히 핵심입니다. GHC 는 확인을 위해 노력해야 RealWorld
하며 이러한 특수 기능은 프로그램의 의도 된 동작을 변경하는 방식으로 최적화되지 않습니다.
개인적으로 (아마도 지금까지 명백한 것처럼),이 "세계를 지나친"모델은 IO
교육적 도구로서 쓸모없고 혼란 스럽다고 생각합니다. (구현에 도움이 되든 모르겠지만, GHC의 경우 역사적인 유물에 가깝다고 생각합니다.)
한 가지 대안은 IO
응답 핸들러가있는 설명 요청으로 보는 것입니다. 이를 수행하는 몇 가지 방법이 있습니다. 아마도 가장 접근하기 쉬운 것은 무료 모나드 구성을 사용하는 것입니다. 특히 다음을 사용할 수 있습니다.
data IO a = Return a | Request OSRequest (OSResponse -> IO a)
이를보다 정교하게하고 더 나은 속성을 가지려면 여러 가지 방법이 있지만 이것은 이미 개선 된 것입니다. 이해하기 위해 현실의 본질에 대한 깊은 철학적 가정이 필요하지 않습니다. 모든 상태는 값을 반환하는 것만 IO
큼 사소한 프로그램 Return
이거나 응답 처리기가있는 운영 체제에 대한 요청입니다. OSRequest
다음과 같이 될 수 있습니다.
data OSRequest = OpenFile FilePath | PutStr String | ...
마찬가지로 OSResponse
다음과 같은 것일 수 있습니다.
data OSResponse = Errno Int | OpenSucceeded Handle | ...
(수행 할 수있는 개선 사항 중 하나는 요청 OpenSucceeded
에서 얻을 수없는 것을 알 수 있도록보다 안전한 유형을 만드는 것 PutStr
입니다.)이 모델 IO
은 일부 시스템에서 해석되는 요청을 설명하는 모델입니다 ( "실제" IO
모나드의 경우 Haskell 런타임 자체), 그리고 아마도 해당 시스템이 응답을 제공 한 핸들러를 호출합니다. 물론 이것은 요청이 어떻게 PutStr "hello world"
처리되어야 하는지를 알려주지 않지만 척하지도 않습니다. 이것이 다른 시스템에 위임되고 있음을 명시합니다. 이 모델도 꽤 정확합니다. 최신 OS의 모든 사용자 프로그램은 무엇이든하기 위해 OS에 요청해야합니다.
이 모델은 올바른 직관을 제공합니다. 예를 들어, 많은 초보자는 <-
연산자와 같은 것을 "unwrapping" IO
으로 보거나 (안타깝게도 강화 된)보기를 IO String
"포함하는"컨테이너 String
(및 컨테이너 를 <-
가져 오는 컨테이너)라고합니다 . 이 요청-응답 관점은 이러한 관점을 분명히 잘못합니다. 안에 파일 핸들이 없습니다 OpenFile "foo" (\r -> ...)
. 이것을 강조하는 일반적인 비유는 케이크 레시피 안에 케이크가 없다는 것입니다.
이 모델은 동시성에서도 쉽게 작동합니다. 우리는 OSRequest
like에 대한 생성자를 쉽게 가질 수 Fork :: (OSResponse -> IO ()) -> OSRequest
있으며 런타임은이 추가 핸들러에 의해 생성 된 요청을 일반 핸들러와 인터리브 할 수 있지만 좋아합니다. 약간의 영리함을 통해이 (또는 관련 기술)을 사용하여 "우리는 OS에 요청하고 상황이 발생한다"고 말하는 대신 동시성과 같은 것을 실제로 직접 모델링 할 수 있습니다. 이것이 IOSpec
라이브러리가 작동하는 방식입니다.
1 Hugs는 연속 형 구현을 사용 IO
했는데, 명시적인 데이터 형식이 아닌 불투명 한 함수를 사용하지만 필자가 설명한 것과 거의 유사합니다. HBC는 또한 이전 요청-응답 스트림 기반 IO에 계층화 된 연속 기반 구현을 사용했습니다. NHC (따라서 YHC)를 사용 썽크, 즉이 약 IO a = () -> a
는하지만 ()
불렸다 World
하지만 국가 통과하고 있지 않습니다. JHC와 UHC는 기본적으로 GHC와 동일한 접근 방식을 사용했습니다.