haskell - 难道 (Alternative f, Foldable f) => Monad f 吗?

标签 haskell monads typeclass alternative-functor foldable

以下类型检查:

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/

相关文章:

haskell - 如何使用 ListT monad 转换器

c++ - Haskell IO monad 的 C/C++ 包装器

haskell - 如何定义类型类同义词

haskell - 在 Haskell 中,有没有办法以多种方式表示类型应该是类型类的实例?

scala - 一元类型构造函数的类型类模式

haskell - 在Windows中编译Haskell程序: is it possible without downloading something such as Cygwin?

haskell - 为什么我的程序使用这么多内存?

haskell - 如何将自由单子(monad)转换为仿函数?

haskell - `mfix` 未按预期工作

haskell - 是否存在渐近优化一系列 MonadPlus 操作的 Codensity MonadPlus?