2015-05-30 2 views
3

Чтение через какой-то код, который я иногда попадаются классов типов, которые с приставкой Monad, примеры из них MonadState, MonadIO, MonadReader и т.д.Почему некоторые стили с префиксом «Monad»?

Что именно цель этого?

Принимая MonadState в качестве примера, я знаю, что

  • State позволяет без гражданства состояние
  • StateT позволяет использовать другие монады, как IO к "объединить" функциональность как

Но MonadState позволяет точно?

Мне не нужна другая группа одинаково названных типов/классных классов, может кто-нибудь объяснить?

+0

Я думаю, что это скорее вопрос о дизайне [MTL] (https://hackage.haskell.org/package/mtl) (правильно?) - почему соглашения об именовании том, что путь кажется немного упрямым для меня ... – Carsten

+0

да, вы правы –

+0

Потому что они подклассы монад! 'class (Monad m) => MonadXYZ m где ...' – AJFarmar

ответ

7

State, StateT и другие типы, как они приходят из transformers, в то время как MonadState и других классов типов, как классы типов Рода из mtl. Обратите внимание, что первые типа, а последние модельные стекла.

Типы от transformers являются экземплярами Monad и MonadTrans. Вы можете работать непосредственно с ними, но есть несколько раздражающих:

  • Если у вас есть стопка монады несколько слоев глубоко, вы должны посыпать код с большим количеством вызовов lift для того, чтобы получить доступ к функциональности каждого уровня.

  • Иногда два разных типа обеспечивают один и тот же «интерфейс». Например, как RWST, так и ReaderT предлагают читательские функции, такие как ask. При написании функции раздражает необходимость совершать одно из другого, уменьшая общность.

В Monad* из mtl классов типов облегчить эти проблемы:

  • Они имеют экземпляры «Сквозные», которые устраняют многие вызовы на lift (или, точнее, обрабатывать их автоматически). Например, StateT является экземпляром MonadState, но ReaderT более StateT также является экземпляром MonadState, поэтому вы можете напрямую использовать get.

    import Control.Monad 
    import Control.Monad.Reader 
    import Control.Monad.State 
    
    -- put the environment in the state 
    bar :: ReaderT Int (State Int)() 
    bar = ask >>= lift . put -- we use lift here 
    
    barMTL :: ReaderT Int (State Int)() 
    -- This ONLY works if we have imported the 
    -- required instances from mtl. 
    -- The MonadState instance for ReaderT, in particular. 
    barMTL = ask >>= put -- the put is auto-lifted 
    
  • Вы можете поставить Monad* ограничение в своих функциях и работе против «интерфейса» Monad* вместо совершения сразу к конкретной реализации монады. Таким образом, ваши функции становятся более общими, и выбор точной «реализации» задерживается до последнего момента.

    import Control.Monad 
    import Control.Monad.State 
    import Control.Monad.RWS 
    
    -- Dumb function that increments the state. 
    -- Doesn't commit to a specific implementation of the monad. 
    baz :: MonadState Int m => m() 
    baz = modify succ 
    
    main :: IO() 
    main = do 
        -- run as State 
        print $ runState baz 0 
        -- run as RWS 
        print $ runRWS (baz >> tell())() 0 
    
+0

Можете ли вы предоставить пример кода «Monad *' typeclasses в действии? –

+0

есть действительно хороший [** учебник **] (https://www.cs.virginia.edu/~wh5a/personal/Transformers.pdf) для этого – Carsten

+0

@Carsten Учебное пособие не распространяется на 'mtl' , хоть. – danidiaz

2

MonadState не является монадой, но является подклассом Monad. State - это монада (а также MonadState). Монадный подкласс MonadState используется для создания таких функций, как get, put. Работает над любой монадой, которая имеет понятие получаемого/устанавливаемого «состояния».

+0

Я не говорил о «MonadState» специально, но любой класс с префиксом «Monad». Я просто использовал «MonadState» как произвольный пример. –

+2

@ElectricCoffee. То же самое касается «MonadReader», «MonadIO», «MonadError» и т. Д. Каждый из них является классом типа, а не типом. Они предоставляются таким образом, что вы можете иметь более общие функции, чем позволяет только «StateT». Вы даже можете определить свой собственный экземпляр «MonadState» (или любой другой) по мере необходимости. Они доступны, чтобы вы не привязывались к «StateT» или «ReaderT» или «IO» или тому подобное. – bheklilr

+0

Не могли бы вы привести пример? –

Смежные вопросы