Haskell 定义类型类时,类型变量不在范围内

Haskell 定义类型类时,类型变量不在范围内,haskell,typeclass,Haskell,Typeclass,我正在写一个mtl风格的变形金刚类型的类。看起来像这样: class (Monad m, Stream s m t) => MonadStuff s m | m -> s where -- function signatures go here… 我想说的是,m应该是Monad的实例 应该是流smt的实例,其中t实际上并不重要,但是 s和m来自定义的右侧(在=>之后) 哈斯克尔说: 不在范围内:类型变量“t” 所以,显然我不能这么做。或者我可以吗?我是否应该删除流SMT 约束,

我正在写一个mtl风格的变形金刚类型的类。看起来像这样:

class (Monad m, Stream s m t) => MonadStuff s m | m -> s where
  -- function signatures go here…
我想说的是,
m
应该是
Monad
的实例 应该是
流smt
的实例,其中
t
实际上并不重要,但是
s
m
来自定义的右侧(在
=>
之后)

哈斯克尔说:

不在范围内:类型变量“t”

所以,显然我不能这么做。或者我可以吗?我是否应该删除
流SMT
约束,并将其添加到类中的每个函数中
另一种方法?

如果事实上,什么是
t
并不重要,那么也许你可以让编写实例的人选择它:

{-# LANGUAGE TypeFamilies #-}
class (Monad m, Stream s m (StuffType m)) => MonadStuff s m | m -> s where
    type StuffType m

或者,既然你已经拥有了MPTCs和FunDPS,你可以考虑这样做,它不需要额外的扩展,但基本上是相同的:

class (Monad m, Stream s m t) => MonadStuff s m t | m -> s t where

然而,我怀疑事实上选择
t
确实很重要:除非
Stream
的fundep至少与
ms->t
一样信息丰富,否则您将无法以有意义的方式使用此约束。在这种情况下,您应该将约束移动到提到
t
的方法的签名中,或者将使用
Stream
方法。

假设您谈论的是parsec中的类,为什么不将
t
添加到
monadsuff
<代码>类流SMT=>MonadStuff SMT m | m->s,s->t@Cirdec,不完全来自Parsec,但还是感谢您的建议。链接答案的解决方案相当难看。我不认为这是重复的,因为这是关于要求所有a的
。约束(Foo a)
而不是所有a的
。Constraint Foo a
,这对我来说似乎根本不同。你能告诉我们你的类的方法是什么样的吗?也许可以将
流mst
约束移动到方法签名中。
流smt
具有fundep
s->t
。然而,它在某种程度上变得复杂了,我将它简化为
Stream st
,因此我最终使用
类(Monad m,Stream st)=>MonadStuff s m t | m->s t where
。这似乎奏效了。