2016-09-28 34 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

相关问题