我试图找出如何为Foo类型实现MonadBaseControl实例,Foo是StateT实例的新类型包装器。您可能会认为它会像这一样实现,但情况似乎并非如此。我假设这个州的问题是在这里引起的,那么有什么办法可以解决这个问题吗?
代码:
newtype Foo a = Foo { unFoo :: StateT Int IO a }
deriving (Monad, Applicative, Functor, MonadBase IO)
instance MonadBaseControl IO Foo where
type StM Foo a = a
liftBaseWith f = Foo $ liftBaseWith $ \q -> f (q . unFoo)
restoreM = Foo . restoreM 错误:
Couldn't match type ‘a’ with ‘(a, Int)’
‘a’ is a rigid type variable bound by
the type signature for restoreM :: StM Foo a -> Foo a
Expected type: a -> StateT Int IO a
Actual type: StM (StateT Int IO) a -> StateT Int IO a
Relevant bindings include
restoreM :: StM Foo a -> Foo a
In the second argument of ‘(.)’, namely ‘restoreM’
In the expression: Foo . restoreM发布于 2015-11-06 02:47:13
为了避免UndecidableInstances,链接的答案扩展了一个类型家族,为了人类的可读性,它真的不应该这样做。也就是说,他写道
instance MonadBaseControl IO Foo where
type StM Foo a = a当人们可能会考虑写
instance MonadBaseControl IO Foo where
type StM Foo a = StM (ReaderT Int IO) a为了更清楚地说明如何为给定的新型包装选择正确的右侧。使用类似的更改(和UndecidableInstances),您的代码可以正常工作。如果您想要避免UndecidableInstances,可以在链接的答案中进行相同的扩展;一个询问ghci应该展开什么的示例如下所示:
> :kind! forall a. StM (StateT Int IO) a
forall a. StM (StateT Int IO) a :: *
= (a, Int)因此,对于StateT版本的Foo,我们也可以编写:
instance MonadBaseControl IO Foo where
type StM Foo a = (a, Int)https://stackoverflow.com/questions/33558234
复制相似问题