문제

Conft와 친구들을 이해하기위한 지속적인 탐구. 아래 (터무니 없지만 예시적인) 코드를 고려하십시오.

v :: IO (Either String [String])
v = return $ Left "Error message"

doit :: IO (Either String ())
doit = (flip runContT return) $ callCC $ \k -> do
    x <- liftIO $ v
    x2 <- either (k . Left) return x
    when True $ k (Left "Error message 2")
    -- k (Left "Error message 3")
    return $ Right () -- success

이 코드는 컴파일되지 않습니다. 그러나 교체하는 경우 when 아래에 댓글이있는 k 호출을 사용하면 컴파일됩니다. 무슨 일이야?

또는 X2 라인을 주석하면 컴파일됩니다. ?

분명히, 이것은 원래 코드의 증류 버전이므로 모든 요소가 목적을 달성합니다. 무슨 일이 일어나고 있는지, 어떻게 고치는 지에 대한 설명 적 도움을주십시오. 감사.

도움이 되었습니까?

해결책

여기서 문제는 유형과 관련이 있습니다. when 그리고 either, contt에 특별한 것이 아님 :

when :: forall (m :: * -> *). (Monad m) => Bool -> m () -> m ()
either :: forall a c b. (a -> c) -> (b -> c) -> Either a b -> c

두 번째 인수는 유형이어야합니다 m () 일부 모나드 m. 그만큼 when 따라서 코드 라인은 다음과 같이 수정 될 수 있습니다.

when True $ k (Left "Error message 2") >> return ()

코드를 컴파일하려면. 이것은 아마도 당신이하고 싶은 일이 아니지만, 무엇이 잘못 될 수 있는지에 대한 힌트를줍니다. k의 유형은 when.

이제 either 서명 : 두 가지 주장에 주목하십시오 either 동일한 유형의 결과를 생성하는 함수 여야합니다. 유형 return 다음은 유형에 따라 결정됩니다 x, 명시 적 서명으로 수정되었습니다. v. 그래서 (k . Left) 비트는 동일한 유형을 가져야합니다. 이것은 차례로 유형을 수정합니다 k 에서 (GHC 결정)

k :: Either String () -> ContT (Either String ()) IO [String]

이것은 호환되지 않습니다 when의 기대.

당신이 댓글을 달 때 x2 그러나 라인은 유형의 체커의 코드보기에 미치는 영향이 제거됩니다. k 더 이상 불편한 유형으로 강요되지 않으며 유형을 자유롭게 가정 할 수 있습니다.

k :: Either [Char] () -> ContT (Either [Char] ()) IO ()

괜찮습니다 when의 책. 따라서 코드가 컴파일됩니다.

마지막으로, 나는 GHCI의 브레이크 포인트 시설을 사용하여 정확한 유형을 얻었습니다. k 두 가지 시나리오에서 - 나는 손으로 그것들을 쓸 수있을만큼 충분한 전문가가없고 그들의 정확성을 보장 할만 큼 충분하지 않습니다. :-) 사용 :break ModuleName line-number column-number 시도해 보려면.

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