如何通过 foldMap 计算 Foldable 的浮点数 属性 的最大值?
How to compute the maximum of a floating point property of a Foldable via foldMap?
假设我有一个带有可测量对象的地图,我想要它们的最大宽度,默认为 0。Foldable
(foldMap
) and Semigroup
(Max
) 的机制看起来很完美,除了我似乎无法引入任意下限。
data Thing
width :: Thing -> Double
maxWidth :: Map k Thing -> Double
maxWidth things = getMax . foldMap (Max . width) $ things
这正确地抱怨 Double
缺少 Bounded
实例,因为 Max a
的 Monoid
实例使用 mempty = minBound
.
我看到 Data.Foldable
的来源使用了 newtype Max
to implement maximum
的不同定义。该变体会很好,但它似乎无法导出:
maxWidth things = fromMaybe 0 . getMax . foldMap (Max . Just . width) $ things
您可以使用 Option
幺半群来为任何 Semigroup
获取一个幺半群实例。 Option a
只是 Maybe a
的新类型包装器,但它的 Monoid
实例只需要 Semigroup a
而不是 Monoid a
。所以我们可以将它与 Max
一起使用:
maximumMaybe :: (Ord a, Foldable t) => t a -> Maybe a
maximumMaybe = fmap getMax . getOption . foldMap (Option . Just . Max)
如果你想要空列表的默认值,你可以使用fromMaybe
:
maximumWithDefault :: (Ord a, Foldable t) => a -> t a -> a
maximumWithDefault d = fromMaybe d . maximumMaybe
另一种选择是只使用 safe
包中的 maximumMay :: (Ord a, Foldable t) => t a -> Maybe a
。
如果您使用的是 base-4.11.0
或更高版本,则不再需要 Option a
类型,因为对 Monoid (Maybe a)
的限制已解除为 Semigroup a
。因此,从 GHC 8.4.1 附带的 base-4.11.0
开始,您可以这样写:
maximumMaybe :: (Ord a, Foldable t) => t a -> Maybe a
maximumMaybe = fmap getMax . foldMap (Just . Max)
假设我有一个带有可测量对象的地图,我想要它们的最大宽度,默认为 0。Foldable
(foldMap
) and Semigroup
(Max
) 的机制看起来很完美,除了我似乎无法引入任意下限。
data Thing
width :: Thing -> Double
maxWidth :: Map k Thing -> Double
maxWidth things = getMax . foldMap (Max . width) $ things
这正确地抱怨 Double
缺少 Bounded
实例,因为 Max a
的 Monoid
实例使用 mempty = minBound
.
我看到 Data.Foldable
的来源使用了 newtype Max
to implement maximum
的不同定义。该变体会很好,但它似乎无法导出:
maxWidth things = fromMaybe 0 . getMax . foldMap (Max . Just . width) $ things
您可以使用 Option
幺半群来为任何 Semigroup
获取一个幺半群实例。 Option a
只是 Maybe a
的新类型包装器,但它的 Monoid
实例只需要 Semigroup a
而不是 Monoid a
。所以我们可以将它与 Max
一起使用:
maximumMaybe :: (Ord a, Foldable t) => t a -> Maybe a
maximumMaybe = fmap getMax . getOption . foldMap (Option . Just . Max)
如果你想要空列表的默认值,你可以使用fromMaybe
:
maximumWithDefault :: (Ord a, Foldable t) => a -> t a -> a
maximumWithDefault d = fromMaybe d . maximumMaybe
另一种选择是只使用 safe
包中的 maximumMay :: (Ord a, Foldable t) => t a -> Maybe a
。
如果您使用的是 base-4.11.0
或更高版本,则不再需要 Option a
类型,因为对 Monoid (Maybe a)
的限制已解除为 Semigroup a
。因此,从 GHC 8.4.1 附带的 base-4.11.0
开始,您可以这样写:
maximumMaybe :: (Ord a, Foldable t) => t a -> Maybe a
maximumMaybe = fmap getMax . foldMap (Just . Max)