以下类型检查:
instance (Applicative f, Alternative f, Foldable f) => Monad f where
(>>=) = flip $ \f -> foldr (<|>) empty . fmap f
-- Or equivalently
a >>= b = getAlt . foldMap Alt . fmap b $ a
这实际上是一个有效的 Monad
实例吗?如果是,为什么不使用?如果否,是否违反任何法律等?我没有证明这个定律成立,但也找不到反例。
最佳答案
这应该是正确身份单子(monad)法则的反例。
下面,我们利用仿函数积 Maybe :*: Maybe
来自GHC.Generics
,但如果愿意的话可以内联。这也是一个适用性、替代性、可折叠性和单子(monad)。我相信这些情况下的图书馆是守法的。
然后我们比较提议的instance Monad
(问题中的那个)到标准库之一。我们发现所提议的实例不满足正确的身份律,而它似乎在库实例中成立(至少在我非常有限的测试中)。
{-# LANGUAGE FlexibleInstances, GeneralizedNewtypeDeriving, TypeOperators #-}
{-# OPTIONS -Wall #-}
module NotAMonad where
import Control.Applicative
import GHC.Generics ((:*:)(..))
-- A basic wrapper to avoid overlapping instances, and to be able to
-- define a custom monad instance.
newtype Wrap m a = Wrap { unWrap :: m a }
deriving (Functor, Applicative, Alternative, Foldable, Show)
-- The proposed instance
instance (Applicative f, Alternative f, Foldable f) => Monad (Wrap f) where
(>>=) = flip $ \f -> foldr (<|>) empty . fmap f
-- This is Applicative, Alternative, and Foldable
type T = Maybe :*: Maybe
-- A basic test
test :: Wrap T Int
test = Wrap (Just 3 :*: Just 4) >>= return
-- result:
-- Wrap {unWrap = Just 3 :*: Just 3}
4
现已替换为3
。不过,我并没有试图解释原因。
我猜这是由Just 3 <|> Just 4 = Just 3
引起的.
使用库 monad 实例,一切看起来都很好:
> (Just 3 :*: Just 4) >>= return
Just 3 :*: Just 4
关于haskell - 难道 (Alternative f, Foldable f) => Monad f 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44156863/