可以在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?