2014-09-05 7 views
6

하스켈은 MonadState s의 인스턴스를 T1에 파생시킬 수 있지만 T2은 매우 비슷합니다. MonadState s에 대한 인스턴스가 자동으로 파생 될 수 있도록 어떤 식으로 T2의 코드를 수정해야합니까?일반화 된 Newtype Deriving

{-# LANGUAGE GeneralizedNewtypeDeriving #-} 

import Control.Monad.Reader 
import Control.Monad.State 

newtype T1 r s a = 
    T1 { runT1 :: ReaderT r (State s) a } 
    deriving (Monad, MonadReader r, MonadState s) 

newtype T2 r s a = 
    T2 { runT2 :: StateT r (State s) a } 
    deriving (Monad, MonadState r, MonadState s) 

답변

7

유형에 MonadState의 두 인스턴스가있을 수 없습니다. MonadState

의 핵심 부분은 | m -> s입니다
class Monad m => MonadState s m | m -> s where 
    get :: m s 
    set :: s -> m() 
    state :: (s -> (a, s)) -> m a 

로 정의되어 있기 때문입니다. 여기에는 FunctionalDependencies 확장자가 필요하며 모든 m에 대해 자동으로 관련 s을 알 수 있다고 명시되어 있습니다. 즉, 임의의 주어진 m에 대해서만 s에 대한 하나의 선택이 유효하다는 것을 의미합니다. 따라서 r ~ s이 아닌 한 MonadState r mMonadState s m 모두 작동하지 않을 수 있습니다. r ~ s이라면, 컴파일러는 그것을 적용 할 기본 모나드를 어떻게 알 수 있습니까? 이 경우 getput 함수를 작성하여 getInner, setInnergetOuter, setOuter 등의 접두사가있는 함수를 만드는 것이 훨씬 쉽고 이해하기 쉽습니다.