これは正しいアイデンティティモナド法の反例であるべきです。
以下、GHC.Generics
のファンクタ製品Maybe :*: Maybe
を利用していますが、必要に応じてインライン化することができます。これはまた、適用可能な、代替の、折りたたみ可能な、およびモナドでもある。私はこれらの事例の図書館が法を遵守していると信じています。
次に、提案されたinstance Monad
(質問の1つ)を標準ライブラリ1と比較します。適切なアイデンティティー法は、提案されたインスタンスには満足していませんが、ライブラリインスタンスで(少なくとも私の限られたテストでは)保持されているように見えます。
{-# 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
によって引き起こされると思います。
は、ライブラリのモナドのインスタンスを使用して、代わりに、すべてが正常に見える:
> (Just 3 :*: Just 4) >>= return
Just 3 :*: Just 4
出典
2017-05-24 11:35:49
chi
*それは*どんな法則も破らないからではありません。モナドの自動導出を望んでいないのは、モナドを別の方法で実装することができるからです。 –
たとえば、連想配列(辞書)をサポートする型クラスがある場合、それをある種の状態モナドとして定義することができます。しかし、おそらくあなたは状態モナドとしてではなく、(エミュレートされた)プロセッサとして機能する連想配列を必要とします。 –