2012-01-29 1 views
45

IO를 통해 MT 스택 (또는 MT 하나)을 사용하는 것이 적합합니다. 모든 행동이 몹시 성가시기 전에 리프트를 사용하는 것을 제외하면 모든 것이 좋습니다! 나는 이것에 관해 정말로 아무것도 할 수 없다고 생각합니다. 그러나 나는 어쨌든 물을 것이라고 생각했습니다.Monad 트랜스포머로 리프트 피하기

전체 블록을 들어 올리는 것을 알고 있지만 실제로 코드가 혼합 유형 인 경우 어떻게해야합니까? GHC가 구문 론적 설탕을 던지면 좋지 않겠습니까 (예 : <-$ = <- lift)?

답변

51

모든 표준 mtl 모나드의 경우 lift은 전혀 필요하지 않습니다. get, put, ask, tell - 모두 스택의 오른쪽 변압기가있는 모나드에서 작동합니다. 누락 된 부분은 IO이며, 심지어 liftIO은 임의의 IO 작업을 임의의 수의 레이어로 들어 올립니다.

이것은 제공되는 각 "효과"에 대한 유형 코드로 수행됩니다. 예를 들어 은 getput입니다. 당신은 변압기 스택 주위에 자신의 newtype 래퍼를 만들려면, 당신은 GeneralizedNewtypeDeriving 확장자 deriving (..., MonadState MyState, ...)을, 또는 자신의 예를 롤백 할 수 있습니다 :

instance MonadState MyState MyMonad where 
    get = MyMonad get 
    put s = MyMonad (put s) 

당신은 선택적으로 노출하거나 결합 된 변압기의 구성 요소를 숨기기 위해 이것을 사용할 수 있습니다 , 다른 인스턴스가 아닌 일부 인스턴스를 정의합니다.

(자신 만의 typeclass를 정의하고 표준 변압기에 대한 상용구 인스턴스를 제공하여 완전히 새로운 모나 딕 효과에 쉽게 접근 할 수 있지만 완전히 새로운 모나드는 거의 없습니다.

+0

오, 나는 바보 같다고 생각합니다. 이전 답변 중 하나에서, 나는 그 시간에 그것을 이해할 수 없다고 언급했습니다. 자, 고마워! – aelguindy

43

콘크리트 모나드 스택 대신에 typeclasses를 사용하여 함수를 모나드 얼릭으로 만들 수 있습니다. ,

bangMe :: Monad m => StateT String m() 

을하지만 :

물론
bangMe :: State String() 
bangMe = do 
    str <- get 
    put $ str ++ "!" 
    -- or just modify (++"!") 

, 당신은 그것뿐만 아니라 변압기로 작동하는지 깨닫는 사람이 쓸 수 있도록 :

은의 당신이 예를 들어,이 기능을한다고 가정 해 봅시다 다른 스택을 사용하는 함수가있는 경우 ReaderT [String] (StateT String IO)() 또는 무엇이든간에 두려워하는 lift 함수를 사용해야합니다. 어떻게 피할 수 있습니까?

트릭은 함수 서명을 더욱 일반화하여 State 모나드가 모나드 스택의 어느 위치 에나 나타날 수 있다고 말합니다.

bangMe :: MonadState String m => m() 

이 어디 모나드 스택 (거의) 상태를 지원하는 모나드로 m을 강제하고, 기능 따라서 이러한 스택 떼지 않고 작동합니다 : 이것은 다음과 같이 이루어집니다.

하나의 문제가 있습니다. IOmtl의 일부가 아니기 때문에 변압기 (예 : IOT) 또는 기본 별 편리한 유형 클래스가 없습니다. IO 작업을 임의로 수행하려는 경우 어떻게해야합니까?

구조에 관해서는 MonadIO!MonadState, MonadReader 등과 거의 동일하게 작동합니다. 유일한 차이점은 약간 다른 리프팅 메커니즘이 있다는 점입니다. 다음과 같이 작동합니다. IO 작업을 수행하고 liftIO을 사용하여 모나드 불가 지론 버전으로 변환합니다. 그래서 :

action :: IO() 
liftIO action :: MonadIO m => m() 

이 방법으로 사용하고자하는 모나드 모든 작업을 변환함으로써, 당신은 어떤 지루한 리프팅없이 원하는만큼 모나드를 꼬이는 수 있습니다.

+0

자세한 답변을 보내 주셔서 감사합니다. 그래도 타이밍에 맞습니다.) – aelguindy

+4

Me와 ehird는이 문제에 대해 다소 다른 해결책을 제시합니다. 당신이 가진 대안을 이해하기 위해 두 응답을 모두 읽을 가치가있을 것입니다. – dflemstr

+1

너무 많은 상용구가 필요합니다. – rightfold