7

我正在尝试定义一个实例:

newtype Join a = Join { getJoin :: a -> Bool }
   deriving Generic

instance Monoid (Join a) where
   f <> g = ???
   mempty = ???

目标是如果列表中的所有函数都为真,则函数 foldMap Join 应该返回 True,如果所有函数都不为真,则返回 false。

我了解 foldMap,以及 Monoid 的 Sum 和 Product 的实例,但是对于编写 Monoid 的新类型实例来说还是很陌生的。任何正确方向的帮助将不胜感激。谢谢你。

4

2 回答 2

9

True如果第一个和第二个函数都返回,您可以True使用(&&). 然后mempty是一个适用于所有输入的Join函数:True

instance Monoid (Join a) where
    Join f <> Join g = Join (\x -> f x && g x)
    mempty = Join (const True)

自从引入 后Semigroup,该(<>)函数就是Semigroup然而的一个实例:

import Control.Applicative(liftA2)

instance Semigroup (Join a) where
    Join f <> Join g = Join (liftA2 (&&) f g)

instance Monoid (Join a) where
    mappend = (<>)
    mconcat js = Join (\x -> all (($ x) . getJoin) js)
    mempty = Join (const True)
于 2020-07-19T16:28:24.933 回答
1

您的类型Join a与 同构,它已经具有您想要的实例。因此,您可以在您的类型上获取实例,而无需自己实现任何东西,如下所示:a -> AllMonoid

{-# LANGUAGE DerivingVia #-}

import Data.Monoid

newtype Join a = Join { getJoin :: a -> Bool }
   deriving Generic -- not needed for the Monoid instance; I only left it here to show you how to do two different kinds of deriving on the same type, since you derived this already in your question
   deriving (Semigroup, Monoid) via (a -> All)
于 2020-08-01T17:27:19.537 回答