可以在Haskell实例声明中组合类型吗?
  我写了一个Haskell类型类,并且使用form (a -> m _)类型来声明它的实例是很方便的,其中m是类型的(* -> *) ,比如monad,而_是一个插槽将保持不饱和状态。  我知道如何编写newtype X amb = X (a -> mb) ,并为X am声明一个实例。  但是我正在寻找的是使用裸露的,未包装的->类型,如果可能的话。 
  如果想要为表单类型(a -> _)声明实例,那么你可以写: 
instance Foo a ((->) a) where ...
  但我不知道如何/是否可以使用表单类型(a -> m _)来完成它。  我想我想在我的实例声明中编写类型构造函数(->) a _和类型构造函数m _ 。 
我想写这样的东西:
instance Foo a ((->) a (m :: *->*)) where ...
要么:
instance Foo a ((->) a (m *)) where ...
但当然这些都不起作用。 是否有可能做到这一点?
具体而言,这是我想要实现的。 我为其他MonadReaders内部(一级)嵌入的MonadReaders编写了一个类型类,如下所示:
{-# LANGUAGE FunctionalDependencies FlexibleInstances
UndecidableInstances  #-}
class MonadReader w m => DeepMonadReader w r m | m -> r where
  { deepask   :: m r
  ; deepask = deepreader id
  ; deeplocal :: (r -> r) -> m a -> m a
  ; deepreader :: (r -> a) -> m a
  ; deepreader f = do { r <- deepask; return (f r) }
  }
instance MonadReader r m => DeepMonadReader w r (ReaderT w m) where
  { deepask = lift ask
  ; deeplocal = mapReaderT . local
  ; deepreader = lift . reader
  }
提供一个如下所示的实例会很好:
instance MonadReader r m => DeepMonadReader w r ((->) w (m :: * ->
*)) where
  { deepask = w -> ask
  ; deeplocal f xx = w -> local f (xx w)
  ; deepreader xx = w -> reader xx
  }
我认为你走错了路,让事情比他们需要的复杂得多。
一些观察:
...(( - >)w(m :: * - > *))...
  让我们来探讨一下你的意思。  您正在将它用于DeepMonadReader类中的类型参数m ,因此它需要是monad。  你能举出一个具有这种类型的monad的具体例子吗?  为什么不使用((->) w) ? 
class MonadReader wm => DeepMonadReader wrm | m - > r其中...
  w从来不会在任何成员签名中出现这一事实,这表明有什么不对劲。 
...我为其他MonadReader内部(一层)内嵌的MonadReaders写了一个类型类型...
我会采取相反的观点。 讨论monad堆栈是有意义的,monad堆栈是另一个monad堆栈的转换版本。 例如:
StateT s (WriterT w IO)   "contains"     IO
WriterT w (Maybe a)       "contains"     Maybe a
monad堆栈m1 “包含”另一个monad m2意味着什么? 这只是意味着有一种方法可以将m2中的计算转换为m1中的计算:
convert ::  m2 a -> m1 a
  当然,这只是在使用monad变压器时lift 。 
为了表达嵌入另一个monad中的monad reader的概念,我将使用这个类型的类:
class HasReader m m' r where ...
  deepAsk :: m r
  deepLocal :: (r -> r) -> m' a -> m a
这里的想法是,一个HasReader的实例表达了这样一个事实,即monad m “包含”monad m“ ,它本身就是一个具有环境r的读者。
deepAsk返回M”,但在米计算环境。
deepLocal使用环境修改函数以m'运行计算,但将其作为以m计算。 请注意这种类型签名与您的不同:我的deepLocal使用不同的monads, m'和m,而您的只是从m到m 。
下一步是决定我们要编写哪些三元组(m,m',r)的HasReader实例。 很明显,你似乎有这样的例子:
m                                    m'                           r
---------------------                -----------                  --
ReaderT s (ReaderT r m)              ReaderT r m                  r
ReaderT t (ReaderT s (ReaderT r m)   ReaderT s (Reader T r m)     s
...
但想要拥有这些实例似乎也是合理的:
StateT s (ReaderT r m)               ReaderT r m                  r
WriterT w (ReaderT r m)              ReaderT r m                  r
MaybeT (ReaderT r m)                 ReaderT r m                  r
...
  但事实证明,我们不需要HasReader类来处理这些情况。  我们可以只写表达,比如M计算”,并lift它为m。 
上一篇: Can one compose types in a Haskell instance declaration?
