2015-08-05 19 views
9

Monad transformatörleri zor ve emin değilim (= iyi sezgiye sahip değilsiniz).Durum (lar) ve istisna (StateTs m) arasındaki fark nedir?

+1

[Bu soru] bölümüne bakın (http://stackoverflow.com/questions/16457111/how-to-design-a-monadic-stack) – luqui

+1

@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

+0

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: –

cevap

13
StateT s (ExceptT e m) 

Bu diyor ki:

  • Başlangıç ​​m
  • , Şimdi bu

devleti ekle o

  • için 'ekleyerek istisnalar' istisnalar ekleyin ile eylemleri sonlandırmak anlamına gelir iki şekilde: ya normal bir dönüş değeriyle veya bir istisna ile.

    '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

  • devleti ekle m
  • ile

    • 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.

  • +2

    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

    4

    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!

    İlgili konular