我正在写一个类型级别的la mtl-style变形金刚。看起来像这样:
class (Monad m, Stream s m t) => MonadStuff s m | m -> s where
-- function signatures go here…
我试图说m
应该是Monad
的实例
应该是Stream s m t
的实例,其中t
并不重要
s
和m
位于定义的右侧(=>
之后)。
哈斯克尔说:
不在范围内:输入变量't'
所以,显然我做不到。或者我可以吗?我应该删除Stream s m t
约束并将其添加到类中的每个函数中,或者存在
另一种方式?
答案 0 :(得分:3)
如果确实t
并不重要,那么也许你可以让编写实例的人选择它:
{-# LANGUAGE TypeFamilies #-}
class (Monad m, Stream s m (StuffType m)) => MonadStuff s m | m -> s where
type StuffType m
或者,既然你已经开启了MPTC和fundeps,你可以考虑这样做,这不需要额外的扩展,但基本相同:
class (Monad m, Stream s m t) => MonadStuff s m t | m -> s t where
但是,我怀疑t
的选择确实很重要:除非Stream
的fundep至少与m s -> t
一样有用,您将无法以有意义的方式使用此约束。在这种情况下,您应该将约束移动到提及t
或将使用Stream
方法的方法的签名中。