Haskell 成对的Monad实例

Haskell 成对的Monad实例,haskell,monads,Haskell,Monads,显示了(,)ab的实例定义,其中a是幺半群的实例 然而,我不知道如何为(,)ab编写类似的东西,b是Monoid的一个实例?我基本上可以做到这一点,只要我能写下定义: instance Monoid b => Monad ((,) ???) where return a = (a,mempty) ~(a,b) >>= f = let (c,b1) in f a in (c,b `mappend` b1) 所以问题是如何编写?部分 更新 实际上,这个问题是一个更

显示了
(,)ab
的实例定义,其中
a
幺半群的实例

然而,我不知道如何为
(,)ab
编写类似的东西,
b
Monoid
的一个实例?我基本上可以做到这一点,只要我能写下定义:

instance Monoid b => Monad ((,) ???) where
    return a = (a,mempty)
    ~(a,b) >>= f = let (c,b1) in f a in (c,b `mappend` b1)
所以问题是如何编写
部分

更新


实际上,这个问题是一个更一般的问题的特例:是否可以编写类型类的实例来作用于某些最后没有出现的类型?在我的例子中,类型构造函数是
(,)ab
,我想让它成为
Monad a
的一个实例,其中
a
不是最后一个类型参数

你不能。对于
Monad
来说,参数的多态性是至关重要的,因此,如果一个特定的monadish对象只对幺半群有意义,那么它就不是Monad


例如,
return::Monad m=>a->ma
。您无法为
return

的签名添加额外的约束。我们可以编写,因为现在同义词不适合这种情况,所以我们使用newtype:

newtype RevTuple b a = RevTuple { totuple :: (a , b) }

instance Monoid b => Monad (RevTuple b) where
    return a = RevTuple (a,mempty)
    (RevTuple (a,b)) >>= f = 
                 let RevTuple (c,b1) = f a in RevTuple (c,b `mappend` b1)

请参考我的更新。关键是我想让
Monad
实例作用于
(,)a b
a
,而不是
b
。这在任何意义上都等同于现有的
Monad
实例,只是顺序颠倒了。是否有任何原因使您无法使用现有实例并在需要时翻转产品订单?@kqr通常可以在使用前翻转订单。不过我只是想知道,一般来说,我能做到这一点吗?我怎样才能做到?我还发现了其他一些可能有用的案例。另外,我认为反复调用
flip
仍然在重复我自己。啊,那么@wit的
newtype
解决方案是我唯一知道的。这还不够好,因为每次我想使用
RevTuple
时,我都必须使用类型构造函数和
totuple
@eartengine-Hope,稍后我们可以使用类型:
type RevTuple b a=(a,b)
在这种情况下,您已经可以有这样的定义了。问题是在这种情况下不能说
实例Monoid b=>Monad(RevTuple b)
。@EartEngine必须使用
RevTuple
构造函数在技术上并不比必须使用
(,)
构造函数差。感觉更糟的只是因为它是一个较长的名称。当我查看
数据中的
newtype
s时,我意识到这是Haskell中发生的正常情况。所以我认为这是正确的。同样有趣的是,我们可以看到同构类型
(a,a)
(实际上是一个同构类型)是如何以与
(a,b)
完全不同的方式变成
单子的。