可以在Haskell实例声明中组合类型吗?
我已经编写了一个Haskell typeclass,使用可以在Haskell实例声明中组合类型吗?,haskell,typeclass,Haskell,Typeclass,我已经编写了一个Haskell typeclass,使用(a->m_)形式的类型来声明它的实例会很方便,其中m是一种(*->*),比如monad,而是一个不饱和的插槽。我知道如何编写newtypexamb=X(a->mb),并为xam声明一个实例。但我想要的是,如果可能的话,使用裸的、未包装的->类型 如果要声明表单(a->)类型的实例,则可以编写: instance Foo a ((->) a) where ... 但我不知道如何/是否可以使用表单类型(a->m)。我想我想在实例声明中
(a->m_)
形式的类型来声明它的实例会很方便,其中m
是一种(*->*)
,比如monad,而
是一个不饱和的插槽。我知道如何编写newtypexamb=X(a->mb)
,并为xam
声明一个实例。但我想要的是,如果可能的话,使用裸的、未包装的->
类型
如果要声明表单(a->
)类型的实例,则可以编写:
instance Foo a ((->) a) where ...
但我不知道如何/是否可以使用表单类型(a->m)
。我想我想在实例声明中编写类型构造函数(>)a
和类型构造函数m
我想这样写:
instance Foo a ((->) a (m :: *->*)) where ...
{-# 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
}
或:
但这些当然不起作用。有可能这样做吗
具体来说,这就是我想要实现的目标。我为他写了一个打字班
嵌入(一级)其他单体恐惧者中的单体恐惧者,
像这样:
instance Foo a ((->) a (m :: *->*)) where ...
{-# 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::*->*) 让我们来探讨一下你的意思。您将它用于
deepmonader
类中的类型参数m
,因此它需要是monad。你能举一个单子的具体例子吗
有这种类型的吗?为什么不直接使用((->)w)
类monawarder w m=>deepmonawarder w r m | m->r其中
w
从未出现在任何成员签名中这一事实表明存在问题
。。。我为Monawarder编写了一个typeclass,它嵌入到其他Monawarder的内部(一个级别)
我会采取相反的观点。谈论单子堆栈是一种转换的方法是有道理的
另一个monad堆栈的版本。例如:
StateT s (WriterT w IO) "contains" IO
WriterT w (Maybe a) "contains" Maybe a
一个monad堆栈m1包含另一个monadm2意味着什么?
这只是意味着有一种方法可以将m2中的计算转换为m1中的计算:
convert :: m2 a -> m1 a
当然,当使用monad变压器时,这只是提升
为了表达您在另一个monad中嵌入monad阅读器的概念,我将使用
类型类别:
class HasReader m m' r where ...
deepAsk :: m r
deepLocal :: (r -> r) -> m' a -> m a
这里的想法是,一个实例HasReader m'r表达了以下事实:
monadm“包含”一个monadm',它本身就是一个具有
环境r
deepAsk返回m'的环境,但作为m中的计算
deepLocal使用环境修改功能在m'中运行计算
但将其作为计算返回到m。请注意此类型签名与您的不同之处:
我的deepLocal使用不同的单子,m'和m,而你的单子是从m到m
下一步是决定要编写哪些三元组(m,m',r)
of拥有阅读器。很明显,你脑海中似乎有这样的例子:
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谢谢。您提出了几个建议:(1)将实例的类型更改为(->)w,或者将类的第一个参数从外部读取器环境的类型更改为外部读取器monad的类型。(2) 我改变了当地人的生活方式。(3) 我可能想为monad堆栈提供类的实例,这些堆栈只有一层读卡器;在许多这样的情况下,这个课程并没有那么有用或必要。回答(1):这是值得探索的,谢谢。Re(2):我需要一个与我描述的类型相同的deepLocal;虽然它可能有一些优势,但我还没有看到你所提议的深度。我会考虑一下。Re(3):事实上,对于您的第二组案例,我们不需要HasReader类,我们也不需要自己执行lift
ing,因为它已经写入到您的m
monad的monader实例中。我的deepmonawarder
类用于堆栈中的外部monawarder“妨碍”更深入嵌入的monawarder的情况,使后者的ask
和local
方法更难访问。当然,人们仍然可以通过使用lift
、mapReader
等正确组合来获取它们;但是这些组合并不总是显而易见的…Re(3)-为什么不给出一个具体的例子,说明您想使用DeepReader类,我们将看到选项是什么。继续讨论。。。