가장 좋은 방법은 전화하는 방법이 아니라 그러한 코드를 분석 하는 방법 입니다. 그리고 그러한 분석에서 나의 첫 번째 주요 질문은 다음과 같습니다.
- 부작용은 함수의 인수 또는 부작용의 결과에 의존합니까?
- 아니요 : "효과적인 기능"은 순수한 기능, 효과적인 행동 및 이들을 결합하는 메커니즘으로 리팩토링 될 수 있습니다.
- 예 : "유효 기능"은 모나드 결과를 생성하는 기능입니다.
이것은 Haskell에서 간단하게 설명 할 수 있습니다. "아니오"사례의 예는 다음과 같습니다.
double :: Num a => a -> IO a
double x = do
putStrLn "I'm doubling some number"
return (x*2)
이 예에서 우리가 취하는 조치 (행 인쇄 "I'm doubling some number"
)는 x
결과와의 관계에 영향을 미치지 않습니다 . 이것은 Applicative
클래스와 *>
연산자를 사용하여 이런 식으로 리팩토링 할 수 있다는 것을 의미 합니다. 이는 함수와 효과가 실제로 직교 함을 보여줍니다.
double :: Num a => a -> IO a
double x = action *> pure (function x)
where
-- The pure function
function x = x*2
-- The side effect
action = putStrLn "I'm doubling some number"
따라서이 경우 개인적으로 순수한 기능을 제외시킬 수있는 경우라고 말합니다. 많은 Haskell 프로그래밍이 이것에 관한 것입니다. 효과적인 코드에서 순수한 부분을 제거하는 방법을 배우십시오.
순수하고 효과적인 부분이 직교하지 않는 "예"정렬의 예 :
double :: Num a => a -> IO a
double x = do
putStrLn ("I'm doubling the number " ++ show x)
return (x*2)
이제 인쇄하는 문자열은의 값에 따라 다릅니다 x
. 그러나 함수 부분 ( x
2를 곱한 값 )은 효과에 전혀 의존하지 않으므로 여전히 요소를 제외시킬 수 있습니다.
logged :: (a -> b) -> (a -> IO x) -> IO b
logged function logger a = do
logger a
return (function a)
double x = logged function logger
where function = (*2)
logger x putStrLn ("I'm doubling the number " ++ show x)
나는 다른 예제들을 계속 설명 할 수는 있지만, 이것이 내가 시작한 요점을 설명하기에 충분하기를 바랍니다. 당신은 무언가를 "부르지"않고 순수하고 효과적인 부분들이 어떻게 관련되어 있는지를 분석하고 그것을 고려하지 않습니다. 당신의 이점에.
이것이 Haskell이 Monad
클래스를 광범위하게 사용하는 이유 중 하나입니다 . 모나드는 이런 종류의 분석 및 리팩토링을 수행하는 도구입니다.