newtype Comparison a定义于Data.Functor.Contravariant.
在定义的此模块的版本中contravariant-1.5,Monoid实例on Contravariant定义如下:
instance Monoid (Comparison a) where
mempty = Comparison (\_ _ -> EQ)
mappend (Comparison p) (Comparison q) = Comparison $ mappend p q
Run Code Online (Sandbox Code Playgroud)
Data.Functor.Contravariant也用基数定义(显然是GHC 8.6.1).在base中,Monoid实例on Comparison定义如下:
deriving instance Semigroup (Comparison a)
deriving instance Monoid (Comparison a)
Run Code Online (Sandbox Code Playgroud)
什么使实例Monoid (Comparison a)能够在base中自动派生?
我应该在哪里查看mempty和mappend它的定义?
对于newtypes,GeneralizedNewtypeDeriving启用后,将使用基础类型的实例获取实例.
因此,mempty @ a -> a -> Ordering使用(同上mappend),然后重新包装为mappend :: Comparison a.
请注意,这最终都涉及到对函数类型的半群/独异的实例b -> c和药粥Ordering.
类型Comparison只是一个newtypeover a -> a -> Ordering。
OrderingSemigroup我认为是一个定义在 中的实例GHC.Base。
另一个相关实例Semigroup是:
Semigroup b => Semigroup (a -> b)
Run Code Online (Sandbox Code Playgroud)
也就是说,任何函数类型如果a -> b有Semigroup实例,则也b有Semigroup实例。
您可以将a -> a -> Ordering其视为,即一个接受输入并返回输出的a -> (a -> Ordering)函数。既然是一个实例,那么也是。a(a -> Ordering)(a -> Ordering)Semigroupa -> (a -> Ordering)
同样的推理也适用于Monoid.
最后,正如 chi 在另一个答案中所写的那样,GeneralizedNewtypeDeriving负责剩下的事情。