2016-09-28 76 views
6

我有一個代碼,適用於一個monad,它有一定的狀態。 我遇到了問題,因爲狀態有一個需要monad的類型變量。當一個類型包含它自己時該怎麼辦?

它看起來像:

myget :: MonadState (MyState m A) m => m A 

現在,當我嘗試,使之更加具體,有一個問題。例如。只是StateT(一些內部單子im):

myget' :: StateT <loops here> im A 
myget' :: StateT (MyState <loop> A) im A 
myget' :: StateT (MyState (MyState <loop> A) A) im A 
myget' :: StateT (MyState (MyState (MyState <loop> A) A) A) im A 
... 
myget' = myget 

所以,很顯然,我不能寫這種類型的簽名;我甚至不能把它留給類型推理。

我該如何解決這個問題?
我確實通過使myget(第一個常規定義)在monad變換器上工作來解決問題,而且它確實有效,但是代碼與其他任何東西都不能很好地配合使用(因爲通常人們會使用monads變形金剛就像monads),所以它不是一個很好的解決方案。

任何想法?

+0

http://www.haskellforall.com/2012/06/you-could-have-invented-free-monads.html – arrowd

+0

是什麼'MyState'的樣子,順便說一下? – dfeuer

+2

你可以用'MonadState(MyState MSM A)MSM'的行來定義你自己的monad,'MSM'嗎? –

回答

4

newtype來救援! A newtypedata聲明可以打破循環。

newtype MS s m a = MS 
    {getMS :: StateT (MyState (MS s m) s) m a} 
    deriving (Functor, Applicative, Monad) 

deriving instance Monad m => 
    MonadState (MyState (MS s m) s) (MS s m) 

instance MonadTrans (MS s) where 
    lift = MS . lift 
+0

太棒了!我無法正確地獲取表格;非常感謝!附: 'GeneralizedNetypeDeriving'足以導出實例。 – MasterMastic

+0

@MasterMastic,我剛剛調換了參數順序以獲得一個'MonadTrans'實例。我不在我的電腦,所以我不知道GND是否也可以派生出來。 – dfeuer

+0

是的,對於我來說,'MonadTrans'通常不適用於廣義的newtype派生,但這是唯一的一個。你確實翻轉了它是很好的;現在有通常的順序。 – MasterMastic

相關問題