最大值的惯用性,单声道版本是什么样的



如何获得有效容器的最大元素,其中计算属性与之比较也触发效果?

必须有更多可读性的做事方式:

latest dir = Turtle.fold (z (ls dir)) Fold.maximum
z :: MonadIO m => m Turtle.FilePath -> m (UTCTime, Turtle.FilePath)
z mx = do
    x <- mx
    d <- datefile x
    return (d, x)

我使用了超载版本,而不是未载荷的maximumBy,但后者似乎更好地用于临时属性选择。

如何解决类似问题的方法?

,所以我对海龟一无所知;不知道这是否非常适合乌龟生态系统。但是,由于您在评论中说服我maximumByM值得手工写作,所以这就是我这样做的方式:

maximumOnM :: (Monad m, Ord b) => (a -> m b) -> [a] -> m a
maximumOnM cmp [x] = return x -- skip the effects if there's no need for comparison
maximumOnM cmp (x:xs) = cmp x >>= b -> go x b xs where
    go x b [] = return x
    go x b (x':xs) = do
        b' <- cmp x'
        if b < b' then go x' b' xs else go x b xs

我通常更喜欢在事物的版本上 *将映射到 Ord orable元素映射到 *by版本的函数 - 它采用直接进行比较的函数。maximumByM会相似,但具有类似于Monad m => (a -> a -> m Ordering) -> [a] -> m a的类型,但这可能会迫使您重做每个a的效果,我猜这不是您想要的。我发现 *经常与我想做的事情和我想要的性能特征相匹配。

由于您已经熟悉Fold,因此您可能想了解FoldM,这是相似的。

data FoldM m a b =
  -- FoldM step initial extract
  forall x . FoldM (x -> a -> m x) (m x) (x -> m b)

您可以写:

maximumOnM ::
  (Ord b, Monad m)
  => (a -> m b) -> FoldM m a (Maybe a)
maximumOnM f = FoldM combine (pure Nothing) (fmap snd)
  where
    combine Nothing a = do
      f_a <- f a
      pure (Just (f_a, a))
    combine o@(Just (f_old, old)) new = do
      f_new <- f new
      if f_new > f_old
        then pure $ Just (f_new, new)
        else pure o

现在,您可以使用Foldl.foldM在列表(或其他Foldable容器(上运行折叠。像Fold一样,FoldM具有Applicative实例,因此您可以将多个有效的折叠结合到一个交织在一起的效果并结合其结果的折叠中。

可以使用还原器软件包对折叠式运行效果。

我不确定它是否正确,但是它利用现有的组合和实例(Bounded (Maybe a)除外(。

import Data.Semigroup.Applicative (Ap(..))
import Data.Semigroup.Reducer (foldReduce)
import Data.Semigroup (Max(..))
import System.IO (withFile, hFileSize, IOMode(..))
-- | maxLength
--
-- >>> getMax $ maxLength ["abc","a","hello",""]
-- 5
maxLength :: [String] -> (Max Int)
maxLength = foldReduce . map (length)
-- | maxLengthIO
--
-- Note, this runs IO...
--
-- >>> (getAp $ maxLengthIO ["package.yaml", "src/Lib.hs"]) >>= return . getMax
-- Just 1212
--
-- >>> (getAp $ maxLengthIO []) >>= return . getMax
-- Nothing
maxLengthIO :: [String] -> Ap IO (Max (Maybe Integer))
maxLengthIO xs = foldReduce (map (fmap Just . f) xs) where
    f :: String -> IO Integer
    f s = withFile s ReadMode hFileSize
instance Ord a => Bounded (Maybe a) where
    maxBound = Nothing
    minBound = Nothing

最新更新