2010-11-09 63 views
15

可以說我有一個功能結合StateT和國家單子

f :: State [Int] Int 

和功能:

g :: StateT [Int] IO Int 

我想使用gf,並通過他們之間的狀態。是否有庫函數
StateT (return . runState f)?或者一般來說,給定一個具有相應monad的monad變換器,是否有庫函數?

+0

我相信TomMD的編輯不正確。我相信原來的'g :: StateT [Int] IO Int'應該是站得住腳的。 – glguy 2010-11-10 06:59:09

+0

我喜歡其他的變化,修正了括號...... – HaskellElephant 2010-11-10 10:24:43

+1

這個問題看起來像我在找什麼,但答案都比http://stackoverflow.com/questions/17325485/combining-statet- io-with-state,爲我完成了工作。 – crockeea 2013-09-29 19:39:55

回答

5

在更普遍的情況下,你要做的是將變換應用到變壓器堆棧的內層。對於任意兩個單子,類型簽名可能是這個樣子:

fmapMT :: (MonadTrans t, Monad m1, Monad m2) => (m1 a -> m2 a) -> t m1 a -> t m2 a 

基本上是一個更高層次的fmap。事實上,它可能會賺更多的意義,它與地圖上的最後一個參數,以及結合:

fmapMT :: (MonadTrans t, Monad m1, Monad m2) => (m1 a -> m2 b) -> t m1 a -> t m2 b 

顯然,這不會在所有情況下是可能的,雖然當「源」單子是Identity它可能會更容易,但我可以想象爲它工作的地方定義另一個類型的類。我不認爲典型的monad變壓器庫中有這樣的東西;然而,在一些hackage瀏覽變成了非常相似的東西in the Monatron package

class MonadT t => FMonadT t where 
    tmap' :: FunctorD m -> FunctorD n -> (a -> b) 
      -> (forall x. m x -> n x) -> t m a -> t n b 

tmap :: (FMonadT t, Functor m, Functor n) => (forall b. m b -> n b) 
     -> t m a -> t n a 
tmap = tmap' functor functor id 

在爲tmap'簽名時,FunctorD類型基本上都是fmap特設實現的,而不是直接使用Functor實例。

此外,兩函子樣型構造F和G,與一類像(forall a. F a -> G a)功能描述a natural transformation從F到G.有相當可能是另一個要某處category-extras包,但我變壓器地圖的實現我不確定單子變壓器的分類理論版本是什麼,所以我不知道它會被稱爲什麼。

由於tmap只需要一個Functor實例(任何Monad必須具備)和自然轉化,任何Monad具有不同於return提供的Identity單子自然的改造,你想要的功能,可以對任何情況下一般寫FMonadT as tmap (return . runIdentity) - 假設「基本」monad被定義爲適用於Identity的變壓器的同義詞,無論如何,變壓器庫通常就是這種情況。回到你的具體例子,請注意,Monatron確實有FMonadT的實例StateT

+0

我還沒有看過Monatron軟件包。我必須仔細觀察才能判斷它。我確實喜歡定義一個類型類的時候它的工作原理,任何人都可以證實或否認Monatron做到這一點? – HaskellElephant 2010-11-09 21:56:52

4

對於所有monad變壓器,這樣的功能是不可定義的。例如,Cont r monad無法升級到ContT r IO,因爲這需要將IO monad(a -> IO r)中的延續變爲純延續(a -> r)。

+0

沒有想到這一點。就像你說的那樣,這對每個monadtransformer都是不可能的。因此,它需要變壓器和相應的monad之間的特殊連接...... – HaskellElephant 2010-11-09 21:50:23

+0

難道轉換是另一種方式嗎?因爲連續類型中的'r'通常是多態的,所以你可以直接寫'(ContT runCont):: Cont(m r)a - > ContT r m a'。 – 2010-11-09 22:00:16

+0

@camccann我正在尋找一個廣義的變換類(Monad m => m a - >(TransformerOf m)m'a)(濫用符號)。如果你嘗試爲(繼續 - >繼續)寫一個實例,那麼你將會陷入我描述的那個點。 – Heatsink 2010-11-09 22:50:19

4

你所要求的是從單子StateT mStateT n的映射(被稱爲單子射)。我將使用mmorph庫,它提供了一套非常好的工具來處理monad態射。

要執行State -> StateT m改變你所尋找的,我們將通過定義一個射來概括Identity單子嵌入State開始,

generalize :: Monad m => Identity a -> m a 
generalize = return . runIdentity 

下一步,我們將要解除這種同態作用於你的StateT的內部monad。也就是說,我們需要一個給定從一個單元映射到另一單元的函數(例如,我們的generalize態射函數),它會給我們一個作用於單體變壓器的基本單元的函數,例如, t Identity a -> t m a。你會發現這類似於mmorphMFunctor類的hoist功能,

hoist :: Monad m => (forall a. m a -> n a) -> t m b -> t n b 

把拼在一起,

myAction :: State s Int 
myAction = return 2 

myAction' :: Monad m => StateT s m Int 
myAction' = hoist generalize myAction