약한 변형
가 StateT
위한 실용적 변환기를 정의하는 것이 가능하지 않지만, 그것은 것이 가능 작동하는 약한 변형을 정의하십시오. 상태가 s -> m (a, s)
인 대신 다음 상태를 결정 (따라서 m
은 모나드 여야 함)하고 m (s -> (a, s))
또는 이와 동등하게 m (State s a)
을 사용할 수 있습니다.
import Control.Applicative
import Control.Monad
import Control.Monad.State
import Control.Monad.Trans
newtype StateTA s m a = StateTA (m (State s a))
이 StateT
보다 확실히 약하다.모든 StateTA
는 StateT
로했다 (하지만 그 반대의 경우도 마찬가지) 할 수 있습니다 Functor
및 Applicative
정의
toStateTA :: Applicative m => StateTA s m a -> StateT s m a
toStateTA (StateTA k) = StateT $ \s -> flip runState s <$> k
는 m
기본으로 State
의 동작을 올리는 단지 문제이다 :
instance (Functor m) => Functor (StateTA s m) where
fmap f (StateTA k) = StateTA $ liftM f <$> k
instance (Applicative m) => Applicative (StateTA s m) where
pure = StateTA . pure . return
(StateTA f) <*> (StateTA k) = StateTA $ ap <$> f <*> k
우리가 정의 할 수 있습니다 lift
의 실용적 변형 :
lift :: (Applicative m) => m a -> StateTA s m a
lift = StateTA . fmap return
업데이트 : 실제로 두 개의 응용 펑터의 구성은 항상 모나드와 달리 적용 가능한 펑터이므로 위의 것은 필요하지 않습니다. 우리 StateTA
자동 Applicative
인 Compose m (State s)
에 동형 :
따라서
instance (Applicative f, Applicative g) => Applicative (Compose f g) where
pure x = Compose (pure (pure x))
Compose f <*> Compose x = Compose ((<*>) <$> f <*> x)
우리가 쓸 수있는 단지
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import Control.Applicative
import Control.Monad.State
import Data.Functor.Compose
newtype StateTA s m a = StateTA (Compose m (State s) a)
deriving (Functor, Applicative)
흥미롭게도, 다른 변압기가있다 (예를 들어,'WriterT','ExceptT'), 그' Applicative 인스턴스는 기본 타입 생성자가 Monad이어야합니다. – kirelagin