我编写了一个Haskell类型类,使用(a -> m _)
形式的类型来声明它的实例会很方便,其中m
属于(* -> *)
类,例如monad ,_
是一个不受限制的槽。我知道如何编写newtype X a m b = X (a -> m b)
,并为X a m
声明一个实例。但我正在寻找的是使用裸露的,未包装的->
类型,如果可能的话。
如果想要为(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
}
答案 0 :(得分:2)
我认为你走错了轨道并且正在制造更多东西 比他们需要的要复杂。
一些观察结果:
...(( - &gt;)w(m :: * - &gt; *))...
让我们来探讨你的意思。您正在将其用于m
类中的类型参数DeepMonadReader
,因此它必须是monad。你能给出一个monad的具体例子吗?
有这种类型?为什么不使用((->) w)
?
类MonadReader w m =&gt; DeepMonadReader w r m | m - &gt;在哪里......
w
永远不会出现在任何成员签名中这一事实表明有些不妥。
...我为MonadReaders编写了一个类型类,它嵌入了其他MonadReaders的内部(一级)......
我会采取相反的观点。谈论转换的monad堆栈是有意义的 另一个monad堆栈的版本。 E.g:
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阅读器的概念,我会用它 类型类:
class HasReader m m' r where ...
deepAsk :: m r
deepLocal :: (r -> r) -> m' a -> m a
这里的想法是实例 HasReader m m'r 表达了这样的事实 monad m “包含”monad m'本身就是一个读者 环境 r 。
deepAsk 会返回 m'的环境,但会在 m 中进行计算。
deepLocal 使用环境修改功能在 m'中运行计算 但是将其作为 m 中的计算返回。请注意此类型签名与您的签名有何不同: 我的 deepLocal 使用不同的monad, 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 。