如何为两个参数都具有相同类型的对编写monad实例?

Ste*_*orn 4 monads haskell

假设我有一个对类型:

data Pair a = Pair a a
Run Code Online (Sandbox Code Playgroud)

为它编写monad实例的正确方法是什么?我的想法大致是这样的:

instance Semigroup a => Semigroup (Pair a) where
  Pair a1 a2 <> Pair b1 b2 = Pair (a1 <> b1)(a2 <> b2)

instance Monad Pair where
  return = pure
  (Pair a b) >>= f = f a <> f b
Run Code Online (Sandbox Code Playgroud)

这是对的吗?如果是这样,那么在对中指定b型中的b类型是一个半群?

Aad*_*hah 5

实际上,的唯一正确的monad实例Pair如下。

instance Monad Pair where
    m >>= f = joinPair (f <$> m)

joinPair :: Pair (Pair a) -> Pair a
joinPair (Pair (Pair x _) (Pair _ y)) = Pair x y
Run Code Online (Sandbox Code Playgroud)

这是正确的monad实例的原因是因为它Pair是一个可表示的函子

instance Representable Pair where
    type Rep Pair = Bool

    index (Pair x _) False = x
    index (Pair _ y) True  = y

    tabulate f = Pair (f False) (f True)
Run Code Online (Sandbox Code Playgroud)

事实证明,对于每个可表示的函子,(>>=)都等效于以下bindRep函数。

bindRep :: Representable f => f a -> (a -> f b) -> f b
bindRep m f = tabulate (\a -> index (f (index m a)) a)
Run Code Online (Sandbox Code Playgroud)

如果我们将bindRep功能专门化,Pair则会得到以下结果。

bindRep :: Pair a -> (a -> Pair b) -> Pair b
bindRep (Pair x y) f = tabulate (\a -> index (f (index (Pair x y) a)) a)
                     = Pair (index (f x) False) (index (f y) True)
--                          |_________________| |________________|
--                                   |                   |
--                           (1st elem of f x)   (2nd elem of f y)
Run Code Online (Sandbox Code Playgroud)

以下Adelbert Chang的博客文章对此进行了更好的解释。用可表示的函子进行推理

  • 你的证明始于(并且关键取决于)定义“return x = Pair xx”。这是 Haskell 中唯一合理的定义——但仅仅是因为参数化。在非参数上下文中,人们可能想知道是否“return 0 = Pair 1 2;” 例如, return x = Pair xx` 可能是一个可能的选择。 (2认同)
  • @AaditMShah 我怀疑您的文本中“kx”的两个独立实例都是“hx”,对吗?如果是这样,那么我认为你的论点仍然有很多漏洞,在我看来——我们在问是否存在合法的非参数定义,但你似乎争论的是非法的非参数定义存在。 (2认同)