2017-11-16 8 views
6

하스켈에서 인쇄 된 순수 함수입니다. 그 이유는 무엇? 나는 순수한 함수가 항상 같은 값을 반환하지 않기 때문에 그것이 아니라고 생각하고있다.Haskell이 순수한 함수로 인쇄 되었습니까?

+5

'print'는 무엇을 반환합니까? –

+1

내장 된 모든 불순한 기능에는 이름에'unsafe'라는 단어가 있습니다. 그래서'print'는 순수합니다. 동일한 매개 변수가 주어지면 동일한 결과를 반환합니다. – 4castle

+0

@ 4castle 필연적 인 것은 아니지만 대개 '안전하지 않은 것'은 함수가 합계가 아니라는 사실에 관한 것입니다. – freestyle

답변

2

순수 함수의 태그 (동일한 인수 값에서 항상 동일한 결과 값을 평가하고 의미 상 관찰 가능한 부작용이나 출력을 발생시키지 않는 함수, 예를 들어, ., 없음 ... 그것을 당신은 항상 IO()를 반환,이 트릭을 찾을 수

putStrLn :: String -> IO() 

: 그래서, 다음 가변 객체 또는 출력 I/O 장치에 대한)과 인쇄의 종류에 생각 효과를냅니다. 따라서 Referential Transparency은 순수하지 않습니다. 예를 들어 getLineIO String을 반환하지만 순수 함수이기도합니다. (@interjay 기여도), 내가 말할 노력하고있어, 대답은 질문의 매우 가까이 달려 있다는 것입니다 :

가치의 문제에 IO()는 항상 동일한 입력에 대해 동일한 IO() 값이됩니다. 그 IO()의 실행이 부작용 (이 경우 너무 순진한 모습에, 화면에 문자열을 넣어 가질 수 있기 때문에

과 실행의 문제에

, 그것은 순수한 것이 아니라 일부 IO 수 점심 핵 폭탄, 그리고 는 현재 @ 벤의 좋은 접근 방식을 더 잘 이해할 수

지능 42)을 반환 :

" 을"순수하게 "조작하는 방법을 설명하는 데는 여러 가지 방법이 있습니다. 하나는 IO가 상태 모나드와 같다고 말하면서 만 상태가 쓰여지고 프로그램 밖에있는 상태입니다 = (그래서 당신의 Stuff -> IO DBThing 함수는 세상을받는 여분의 숨겨진 인자를 가지고 있습니다 실제로 다른 세계와 함께 DBThing을 반환하며 항상 다른 세계에서 호출되므로 동일한 Stuff와 함께 호출 할 때 012TB_E_KR까지 다른 DBThing 값을 반환 할 수 있습니다. 또 다른 설명은 IO DBThing 값 자체가 명령형 프로그램이라는 것입니다. . 당신의 하스켈 프로그램은 IO를 수행 불순한 프로그램 을 반환하지 IO를 수행하지 않는 완전히 순수 기능, 하스켈 런타임 시스템 (impurely) "가 반환 프로그램을 실행

그리고 @Erik Allik 입니다 : 입력 IO (A)의 값을 반환 런타임에서 실행되고 있지 기능이 실제로

그래서 하스켈 기능 -. 실행됩니다 무슨 일이 그래서 이러한 기능은 실제로 순수하지만 자신을 값 자체 IO입니다 반환 값은 비 목적을 나타냅니다. 전자 계산.당신이 할 수있는

IO Int의 값은 정말 Int하지 여기 Understanding pure functions in Haskell with IO

+0

Sneaky Haskell :) – HFBrowning

+1

@HFBrowning 그래서 규칙이 있습니다. 그래서 모나드가 규칙을 따르는 이유는 모두가 haskell을 좋아하는 이유입니다. 일단 여러분이 그것의 일부를 작성하면, 순수한 함수, 순수한 사랑 ahaahah –

+1

분명히 타입에 필요하기 때문에 항상 IO()를 반환합니다. 그러나 질문은 그것은 항상'IO()'의 _same_ 값을 반환합니다. – Lee

5

을 발견했다. 이것은 "하스켈 런타임과 같은 방식으로 Int 값을 생산하십시오."라고 읽는 종이와 비슷합니다. 이 종이는 비활성이며 결국 런타임에 의해 생성 된 Int이 다른 경우에도 동일하게 유지됩니다.

main에 할당하여 런타임에 종이를 보냅니다. IO 동작이 main의 방식으로 절대로 발생하지 않고 일부 컨테이너 내부에서 절름발이 인 경우 절대로 실행되지 않습니다.

IO 작업을 반환하는 함수는 다른 함수와 마찬가지로 순수합니다. 그들은 항상 같은 종이를 반환합니다. 이러한 지침으로 런타임이 수행하는 작업은 또 다른 문제입니다. 그들은 순수 '의 t을 weren 히 경우

, 우리는 print 순수 함수,

foo :: (Int -> IO Int) -> IO Int 
foo f = let x = f 0 in liftA2 (+) x x 
+0

런타임에 'IO X'와 'X'는 실제로 같은 방식으로 표현됩니다. 컴파일러는'IO X'가 어떻게 동작하는지에 대한 특별한 것들을 알고 있습니다 (그리고 순수한 값들이 어떻게 동작하는지에 대한 특별한 것들 - 위반할 수있는 가정들)! 이 가정을 사용하여 최적화 된 코드를 생성합니다. 지침 (즉, "종이 조각")으로서의 IO의 관점은 여전히 ​​유용합니다. 그러나 '실행 시점의 가치'와 관련해서 생각해서는 안되며, '논리적 인 객체로서의 가치'와 관련해서는 안됩니다. – user2407038

+2

@ user2407038 적어도 GHC에서 'IO X'는 [매우 다른 표현입니다] (https://hackage.haskell.org/package/base-4.10.0.0/docs/src/GHC.Base.html#line- 1197). –

0

예에

foo :: (Int -> IO Int) -> IO Int 
foo f = liftA2 (+) (f 0) (f 0) 

을 변경하기 전에 두 번 생각해야합니다. 반환하는 값은 IO() 유형이며, 전달한 문자열을 출력하는 코드 묶음으로 생각할 수 있습니다. 전달한 각 문자열에 대해 항상 동일한 코드가 반환됩니다.