可以說我有一個功能結合StateT和國家單子
f :: State [Int] Int
和功能:
g :: StateT [Int] IO Int
我想使用g
f
,並通過他們之間的狀態。是否有庫函數
StateT (return . runState f)
?或者一般來說,給定一個具有相應monad的monad變換器,是否有庫函數?
可以說我有一個功能結合StateT和國家單子
f :: State [Int] Int
和功能:
g :: StateT [Int] IO Int
我想使用g
f
,並通過他們之間的狀態。是否有庫函數
StateT (return . runState f)
?或者一般來說,給定一個具有相應monad的monad變換器,是否有庫函數?
在更普遍的情況下,你要做的是將變換應用到變壓器堆棧的內層。對於任意兩個單子,類型簽名可能是這個樣子:
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
。
我還沒有看過Monatron軟件包。我必須仔細觀察才能判斷它。我確實喜歡定義一個類型類的時候它的工作原理,任何人都可以證實或否認Monatron做到這一點? – HaskellElephant 2010-11-09 21:56:52
對於所有monad變壓器,這樣的功能是不可定義的。例如,Cont r
monad無法升級到ContT r IO
,因爲這需要將IO monad(a -> IO r
)中的延續變爲純延續(a -> r
)。
沒有想到這一點。就像你說的那樣,這對每個monadtransformer都是不可能的。因此,它需要變壓器和相應的monad之間的特殊連接...... – HaskellElephant 2010-11-09 21:50:23
難道轉換是另一種方式嗎?因爲連續類型中的'r'通常是多態的,所以你可以直接寫'(ContT runCont):: Cont(m r)a - > ContT r m a'。 – 2010-11-09 22:00:16
@camccann我正在尋找一個廣義的變換類(Monad m => m a - >(TransformerOf m)m'a)(濫用符號)。如果你嘗試爲(繼續 - >繼續)寫一個實例,那麼你將會陷入我描述的那個點。 – Heatsink 2010-11-09 22:50:19
你所要求的是從單子StateT m
到StateT 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
。你會發現這類似於mmorph
的MFunctor
類的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
我相信TomMD的編輯不正確。我相信原來的'g :: StateT [Int] IO Int'應該是站得住腳的。 – glguy 2010-11-10 06:59:09
我喜歡其他的變化,修正了括號...... – HaskellElephant 2010-11-10 10:24:43
這個問題看起來像我在找什麼,但答案都比http://stackoverflow.com/questions/17325485/combining-statet- io-with-state,爲我完成了工作。 – crockeea 2013-09-29 19:39:55