Monad transformatörleri zor ve emin değilim (= iyi sezgiye sahip değilsiniz).Durum (lar) ve istisna (StateTs m) arasındaki fark nedir?
cevap
StateT s (ExceptT e m)
Bu diyor ki:
- Başlangıç
m
- , Şimdi bu
devleti ekle o
'Ekleme durumu', numaralı numaralı normal geri dönüş değerlerinde fazladan bir durum verisinin eklendiği anlamına gelir.
StateT s (ExceptT e m)
'da, istisna yoksa yalnızca bir sonuç durumu alırsınız. Öte yandan
ExceptT e (StateT s m)
diyor ki: O
istisnaları ekleyin o
m
- Başlat 'devlet ekleme 'anlamına gelir Ekstra bit devlet çıkışı,
m
'un dönüş değerlerine dahil edilir.Ancak şimdi, eklediğiniz istisnalar,
StateT
monad numaralı telefonun içinde alternatif dönüş değeri olarak eklenir. Yani her zaman bir durum çıktısı alırsınız ve sonra normal bir dönüş değeri alabilir veya bununla birlikte bir istisna alabilirsiniz.
Bu yüzden bir daha hemen net bir görüntü verebilir > m (s, ya adet) '-' s:) 'için "genişler". ikincisi geri almak onları zor hale hatalı durumları taahhüt ederken, eski, bir hata catchError' 'in oluştuğunda devlete değişiklik geri alma sağlar. Bazı dillerde, aslında bunu istiyorum. Önerilen okuma: http://www.cse.chalmers.se/edu/course/TDA342_Advanced_Functional_Programming/lecture8.html – Centril
Bunu kendim cevapladım ancak diğer cevaplar kabul edilir!
#!/usr/bin/env stack
-- stack runghc --package mtl
{-# LANGUAGE FlexibleContexts #-}
module Main (main) where
import Control.Applicative
import Control.Monad.State
import Control.Monad.Error
import Control.Monad.Trans.Except
import Data.Functor.Identity
test1 :: (MonadState Int m, MonadError String m) => m Bool
test1 = do
put 1
throwError "foobar"
put 2
return False
test2 :: (Alternative m, MonadState Int m, MonadError String m) => m Bool
test2 = do
put 4
test1 <|> return True
runStateExceptT :: Monad m => s -> ExceptT e (StateT s m) a -> m (Either e a, s)
runStateExceptT s = flip runStateT s . runExceptT
runExceptStateT :: Monad m => s -> StateT s (ExceptT e m) a -> m (Either e (a, s))
runExceptStateT s = runExceptT . flip runStateT s
main :: IO()
main = do
print $ runIdentity . runStateExceptT 3 $ test1
print $ runIdentity . runExceptStateT 3 $ test1
print $ runIdentity . runStateExceptT 3 $ test2
print $ runIdentity . runExceptStateT 3 $ test2
O yazdırır:
örneği düşünün(Left "foobar",1)
Left "foobar"
(Right True,1)
Right (True,4)
dışında ExceptT
ile, hala "bir hata atma" anındaki oldu durumunu alırsınız. Muhtemelen istediğin budur.
Bu kombinasyonun, çok numaralı programlamaya benzediğini unutmayın. Bir istisna güvenliği uygulamaları hakkında düşünmelidir, yani ne zaman throwError
!
[Bu soru] bölümüne bakın (http://stackoverflow.com/questions/16457111/how-to-design-a-monadic-stack) – luqui
@luqui Bunu bulamadınız. Yine de bu soruyu saklamak istiyorum: en azından kapsam bakımından daha dar, bu yüzden daha iyi cevaplanabilir. – phadej
Bu arada, lambdabot bir monad-stack-unroller sahip. #haskell kanalında 'unmtl’i deneyin.> M (e Ya (s, a)) 'ExceptT e' iken (Durumluk sm - 's:' Durumluk s (ExceptT em) a' "genişletilmiş" forma sahiptir: –