Haskell에서 System.Info에 액세스하는 것이 IO 작업으로 간주되지 않는 이유는 무엇입니까?


25

모듈에서 System.Info다음 기능을 봅니다.

os :: String
arch :: String
compilerName :: String
compilerVersion :: Version

IO없어요? 그들은 시스템에 액세스하고 있습니다 ... 내가 틀렸습니까? 내 기대는 다음과 같습니다.

os :: IO String
arch :: IO String
compilerName :: IO String
compilerVersion :: IO Version

사용 사례 :

      print os            -- "darwin"
      print arch          -- "x86_64"
      print compilerName  -- "ghc"

답변:


29

런타임에 해당 정보를 얻지 못합니다 . 이들은 시스템에 설치된대로 컴파일러에서 하드 코딩됩니다.

당신의 정의를 보면이 가장 분명 compilerName에서 발견 http://hackage.haskell.org/package/base-4.12.0.0/docs/src/System.Info.html .

compilerName :: String
compilerName = "ghc"

하지만 심지어 os

os :: String
os = HOST_OS

는 정의되지 않은 이름 HOST_OS(대문자로 시작하는 값 ??)으로 정의되며 이는 설치 중에 대체되는 자리 표시 자임을 나타냅니다.

누군가 나를 고칠 수도 있습니다 (제발!). {-# LANGUAGE CPP #-}파일의 맨 위에 있는 pragma는 HOST_OS컴파일하기 전에 C 전처리기에 의해 적절한 문자열로 대체 됨을 제안합니다 .


2
영업 정말 일부 원하는 경우 IO거기를, 래퍼있다 uname(3)Hackage 볼 수는 : hackage.haskell.org/package/bindings-uname
thsutton

19

문제는 좋은 것입니다. 그 답은 프로그램 컴파일마다 정적 값이라는 것입니다. 그것들은 본질적으로 프로그램으로 컴파일되며 그 후에는 절대 바뀌지 않습니다. 따라서 상수로 취급하면 GHC가 사용하는 가정에서 아무것도 깨지지 않습니다. 그리고 IO 액션보다 간단한 상수를 사용하는 것이 더 편리합니다.

그러나 그것은 모든 종류의 레거시 추론입니다. 하스켈은 오래된 언어입니다. (실제로 Java보다 몇 년이 더 오래되었습니다.) 더 이상 모범 사례로 간주되지 않는 추론을 통해 많은 라이브러리가 구축되었습니다. 이것들이 그 예입니다. 그것들을 노출시키는 현대 라이브러리는 아마도 컴파일 후에 결과가 변경되지 않더라도 IO 액션을 만들 것입니다. Int32 비트와 64 비트 플랫폼 사이에서 크기를 변경하는 것과 같은 주목할만한 예외가 여전히 있지만 IO 작업 뒤에 소스 수준에서 상수가 아닌 것을 넣는 것이 더 유용 합니다.

어쨌든 ... 나는 당신의 기대가 견고하다고 말하고 싶습니다. 이러한 유형은 역사적인 이상의 결과입니다.


-9

편집 :이 답변이 다운 투표 된 이유를 설명해 주신 @interjay 및 @Antal Spector-Zabusky에게 감사드립니다. 그들은 썼다

설명서가 약간 잘못되었습니다. 값은 GHC 컴파일러에 하드 코딩됩니다. 48 년이 지난 후에는 실제 코드가 항상 문서보다 우선합니다. – interjay 어제 @ andy256 당신은 문서가 잘못되었다는 것이 절대적으로 옳습니다 (실제로 Francisco가이 질문을 한 이유 중 하나입니다). Haskell에 대한 것은 런타임에 이러한 문자열 값이 다를 수있는 경우 심각한 버그 일 수 있습니다. 변수를 변경할 수 없습니다. 이는 IO 유형 생성자의 중요성입니다. "외부 세계"에 액세스 할 수있는 계산과 결과가 변경 될 수있는 계산을 나타냅니다. 시스템 호출은 IO 조치의 좋은 예입니다. … [1/2] – Antal Spector-Zabusky 9 시간 전 @ andy256… (또 다른 IO 동작은 "전역 카운터 업데이트"일 수 있습니다.) 따라서 String을 볼 때 어떤 통신도 할 수 없다는 것을 알고 있습니다 후드 아래의 OS. 그렇기 때문에 놀랍게도 Haskell에 익숙하지 않은 경우 시스템 호출을 수행하기 위해 os :: String을 구현하는 것이 쉽지 않을 것입니다. 기본 Haskell에서는 이러한 값을 구현할 수 없습니다. 컴파일러와 옵티 마이저를 작동시킬 수도 있습니다 (이론적 인 문제는 아닙니다. 사람들이 비슷한 문제를 겪는 스택 오버플로 답변이 있습니다). [2/2] – Antal Spector-Zabusky 그렇기 때문에 놀랍게도 Haskell에 익숙하지 않은 경우 시스템 호출을 수행하기 위해 os :: String을 구현하는 것이 쉽지 않을 것입니다. 기본 Haskell에서는 이러한 값을 구현할 수 없습니다. 컴파일러와 옵티 마이저를 작동시킬 수도 있습니다 (이론적 인 문제는 아닙니다. 사람들이 비슷한 문제를 겪는 스택 오버플로 답변이 있습니다). [2/2] – Antal Spector-Zabusky 그렇기 때문에 놀랍게도 Haskell에 익숙하지 않은 경우 시스템 호출을 수행하기 위해 os :: String을 구현하는 것이 쉽지 않을 것입니다. 기본 Haskell에서는 이러한 값을 구현할 수 없습니다. 컴파일러와 옵티 마이저를 작동시킬 수도 있습니다 (이론적 인 문제는 아닙니다. 사람들이 비슷한 문제를 겪는 스택 오버플로 답변이 있습니다). [2/2] – Antal Spector-Zabusky 그리고 잠재적으로 컴파일러와 옵티 마이저를 트립합니다 (이론적 인 문제는 아닙니다 – 사람들이 비슷한 문제를 겪는 스택 오버플로 답변이 있습니다). [2/2] – Antal Spector-Zabusky 그리고 잠재적으로 컴파일러와 옵티 마이저를 트립합니다 (이론적 인 문제는 아닙니다 – 사람들이 비슷한 문제를 겪는 스택 오버플로 답변이 있습니다). [2/2] – Antal Spector-Zabusky

현재 두 개의 삭제 투표가 있습니다. 나는 그 과정이 과정을 거치게 할 것이지만 실제로 가치가 있다고 제안한다. 참고로, 그들의 설명은 질문이 약한 것으로 나타 났으며, Haskell 초보자가 내가 한 추론을 쉽게 따를 수 있기 때문에 대답도 그렇습니다.

원래 답변 :

저는 Haskell 프로그래머가 아니지만 이미 제공된 두 가지 답변이 OP가 링크 한 문서와 일치하지 않습니다.

문서에 대한 나의 해석은 다음과 같습니다.

os :: String - "프로그램이 실행중인 운영 체제"가 나타납니다.

이것이 정보를 얻기 위해 시스템 호출을 발행 할 것으로 기대합니다. 프로그램이 컴파일 된 시스템이 실행되는 시스템과 다를 수 있으므로 컴파일러가 삽입 한 값이 될 수 없습니다. 코드가 해석되는 경우 해석기는 결과를 제공 할 수 있으며, 시스템 호출을 통해 얻어야합니다.

arch :: String - "프로그램이 실행되는 머신 아키텍처"가 나타납니다.

다시 말하지만, 이것은 정보를 얻기 위해 시스템 호출을 발행 할 것으로 기대합니다. 프로그램이 컴파일 된 시스템이 실행되는 시스템과 다를 수 있으므로 컴파일러가 삽입 한 값이 될 수 없습니다.

compilerName :: String - "프로그램을 컴파일하거나 해석중인 Haskell 구현"을 제공합니다.

이 값은 확실히 컴파일러 / 인터프리터에 의해 삽입됩니다.

compilerVersion :: String- " compilerName프로그램이 컴파일되거나 해석되는 버전"이 표시 됩니다.

이 값은 확실히 컴파일러 / 인터프리터에 의해 삽입됩니다.

처음 두 번의 호출이 입력을받는 것으로 간주 할 수 있지만 결과는 운영 체제가 보유한 값에서 비롯됩니다. I / O는 일반적으로 보조 스토리지 액세스를 나타냅니다.


3
하스켈에게는 사실이 아닙니다. 여기에서 계산은 순서가 없으며 결과를 캐시 할 수 있습니다. 함수는 순수하므로 함수가 인수를 허용하지 않으면 상수와 비슷합니다. 한 인수의 함수는 해시 맵 또는 사전처럼 보이며 키를 기준으로 값을 계산합니다. 외부 환경을 사용할 수 없으며 이러한 기능으로 시스템 콜을 수행 할 수 없으며 임의의 숫자 또는 현재 날짜를 얻을 수 없습니다. 당신은 실제로 "순서", 또는 환경을 사용하고 싶은 경우에, 당신은 사용에 필요 IO, 상태를 에뮬레이트하는 모나드 연산의 순서를 에뮬레이트
유리 코 발렌 코

"외부 환경을 사용할 수없고, 그런 함수에서 시스템 콜을 할 수 없습니다"– 특히 "당신"이 Haskell 컴파일러 인 경우 가능합니다! Haskell 구현 os :: String이 평가 될 때 시스템 호출 을 수행 하도록 구현하기가 매우 쉽습니다 .
Tanner Swett

2
하스켈에서 IO 모나드의 중요성을 이해하지 못한다고 생각합니다.
Sneftel

@Sneftel 물론입니다. 나는 모든 패러다임에서 48 년 동안 프로그래밍을하고 홀수 컴파일러를 작성한 후에 초기 답변이 문서와 일치하지 않았지만 여전히 그렇지 않기 때문에 대답하기로 결정했습니다. 그것은 분명히 말한다 osarch런타임에 얻을 수있다.
andy256

1
설명서가 약간 잘못되었습니다. 값은 GHC 컴파일러에 하드 코딩됩니다. 48 년이 지난 후에는 실제 코드가 항상 문서보다 우선합니다.
interjay
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.