【问题标题】:Monad instance for pairs对的 Monad 实例
【发布时间】:2013-10-05 20:04:48
【问题描述】:

This question 显示(,) a b 的实例定义,其中aMonoid 的实例。

但是,我不知道如何为(,) a b 写类似的东西,而bMonoid 的一个实例?只要能写出定义,我基本上都可以做到:

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

那么问题是如何写??? 部分?

更新

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

【问题讨论】:

  • 看看同构类型(a,a)(实际上是它的一个同构)如何以与(a,b)完全不同的方式变成Monad也很有趣。

标签: haskell monads


【解决方案1】:

我们可以写,现在同义词不适合这种情况,所以我们使用 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)

【讨论】:

  • 这还不够好,因为每次我想使用RevTuple时,我都必须使用类型构造函数和totuple
  • @EarthEngine 希望,以后我们可以在这种情况下使用类型:type RevTuple b a = (a,b)
  • 你已经可以有这样的定义了。问题是在这种情况下你不能说instance Monoid b => Monad (RevTuple b)
  • @EarthEngine 必须使用RevTuple 构造函数在技术上并不比必须使用(,) 构造函数差。只是感觉更糟,因为它是一个更长的名字。
  • 当我查看Data.Monoid 中的那些newtypes 时,我意识到这是在Haskell 中发生的正常事情。所以我将此标记为正确。
【解决方案2】:

你不能。 Monad 在其参数中具有多态性至关重要,因此如果特定的 monadish 事物仅对 monoid 有意义,那么它就不是 monad。

例如,return :: Monad m => a -> m a。您无法为return 的签名添加额外的约束。

【讨论】:

  • 请参考我的更新。关键是我想让Monad 实例作用于(,) a ba,而不是b
  • 这在任何意义上都等同于现有的Monad 实例,只是顺序颠倒了。您是否有任何理由不能使用现有实例并在需要时翻转产品的顺序?
  • @kqr 通常可以在使用前翻转订单。但是我只想知道一般我可以这样做吗?我该怎么做?我发现了其他一些可能有用的案例。另外,我认为反复调用flip 仍然是在重复自己。
  • 啊,那我只知道@wit的newtype解决方案。
猜你喜欢
  • 1970-01-01
  • 2011-07-18
  • 1970-01-01
  • 2021-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-14
相关资源
最近更新 更多