为什么 Tuple 没有 Monad 实例?
Why does Tuple not have a Monad instance?
我注意到的一件事是 Tuple
没有 Monad
实例。
但是元组确实有一个 Applicative
实例:
instance Monoid a => Applicative ((,) a)
这已经非常严格地限制了我们可以使 Monad
实例成为什么。
让我们看看我们将获得的类型签名:
instance Monoid a => Monad ((,) a)
join :: Monad m => m (m a) -> m a
join :: Monoid a => (a, (a, b)) -> (a, b)
我们还可以看看 Monad 定律:
join $ f <$> pure x == f x
join $ f <$> (mempty, x) == f x
join (mempty, f x) == f x
join (mempty, (a, b)) == (a, b)
join $ pure <$> x = x
join $ pure <$> (a, b) = (a, b)
join (a, (mempty, b)) = (a, b)
此时我们知道以任何一种方式组合 mempty
和 x
都会得到 x
。我们关于 x
的唯一类型信息是它是 Monoid
。所以基本上仅有的两个实现是:
join (a, (b, x)) = (a <> b, x)
和:
join (a, (b, x)) = (b <> a, x)
而其中的第二个使得 ap
和 <*>
不一样。
所以现在我们知道 ((,) a)
的唯一有效 Monad
实例是:
instance Monoid a => Monad ((,) a) where
(a, c) >>= f = let (b, c') = f c in (a <> b, c')
那为什么现在不是这样呢?
好吧,这个问题的答案似乎是我只需要使用 ghc-8.0.1
,它确实给 Tuple
一个 Monad
实例。感谢@Michael 指出这一点。
我注意到的一件事是 Tuple
没有 Monad
实例。
但是元组确实有一个 Applicative
实例:
instance Monoid a => Applicative ((,) a)
这已经非常严格地限制了我们可以使 Monad
实例成为什么。
让我们看看我们将获得的类型签名:
instance Monoid a => Monad ((,) a)
join :: Monad m => m (m a) -> m a
join :: Monoid a => (a, (a, b)) -> (a, b)
我们还可以看看 Monad 定律:
join $ f <$> pure x == f x
join $ f <$> (mempty, x) == f x
join (mempty, f x) == f x
join (mempty, (a, b)) == (a, b)
join $ pure <$> x = x
join $ pure <$> (a, b) = (a, b)
join (a, (mempty, b)) = (a, b)
此时我们知道以任何一种方式组合 mempty
和 x
都会得到 x
。我们关于 x
的唯一类型信息是它是 Monoid
。所以基本上仅有的两个实现是:
join (a, (b, x)) = (a <> b, x)
和:
join (a, (b, x)) = (b <> a, x)
而其中的第二个使得 ap
和 <*>
不一样。
所以现在我们知道 ((,) a)
的唯一有效 Monad
实例是:
instance Monoid a => Monad ((,) a) where
(a, c) >>= f = let (b, c') = f c in (a <> b, c')
那为什么现在不是这样呢?
好吧,这个问题的答案似乎是我只需要使用 ghc-8.0.1
,它确实给 Tuple
一个 Monad
实例。感谢@Michael 指出这一点。