Jak przekonwertować StateT g (Either E) T
na ExceptT E (StateT g Identity) T
?Zamień monady wewnętrzne i zewnętrzne
Może się przydać tutaj mieszanka traverse
i hoist
.
Jak przekonwertować StateT g (Either E) T
na ExceptT E (StateT g Identity) T
?Zamień monady wewnętrzne i zewnętrzne
Może się przydać tutaj mieszanka traverse
i hoist
.
You can't exchange an arbitrary pair of monads. Ale możesz wymienić te dwie szczególne monady. Najłatwiej zrozumieć, jeśli rozszerzysz newtype
s w definicjach tych transformatorów monad.
Biorąc
newtype StateT s m a = StateT { runStateT :: s -> m (s, a) }
i
newtype ExceptT e m a = ExceptT { runExceptT :: m (Either e a) }
rozszerzenie newtype
S w pierwszej typu wypowiedzi daje nam izomorfizm
StateT s (Either e) a <-> s -> Either e (s, a)
natomiast dla drugiego otrzymujemy
ExceptT e (StateT s Identity) a <-> s -> (s, Either e a)
Należy pamiętać, że Either e (s, a)
może lub nie może zawierać wartości s
, natomiast (s, Either e a)
zawsze. Teraz można przejść od tego ostatniego do pierwszego, po prostu przez traverse
w kodzie w funkcji, ale przejście w drugą stronę wymaga pewnego rozumowania specyficznego dla dziedziny: jeśli obliczenie zgłasza błąd, powinniśmy skierować stan przez niezmieniony do łapacza błędu. (Czy jest to słuszne? Uważam, że jest to raczej dyskusyjne.)
stateTEitherToExceptTState :: (s -> Either e (s, a)) -> (s -> (s, Either e a))
stateTEitherToExceptTState f s =
case f s of
Left e -> (s, Left e)
Right sa -> fmap Right sa
Myślę, że 'stateTEitherToExceptTState' nie jest poprawnym morfizmem monady. Jeśli 'm' jest akcją, która nie zawodzi, oraz' f' strzałką Kleisli, która zawsze zawodzi, 'morph (m >> = f)' nie jest równe 'morph m> = morph. f'. – danidiaz
Gdy 'StateT g (Eise) t' nie powiedzie się, nie zapewnia żadnego stanu. Co powinien robić odpowiedni "Wyjątek e (StateT g Tożsamość)"? – danidiaz
Nie mogę przypomnieć sobie dokładnych definicji, ale czy pierwsza monada nie może się zepsuć w zależności od stanu (np. Czy stan jest liczbą parzystą), kiedy druga nie może? – chi