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)
完全不同的方式变成单子的。