Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell maximumBy的惯用、一元版本会是什么样子?_Haskell_Monads - Fatal编程技术网

Haskell maximumBy的惯用、一元版本会是什么样子?

Haskell maximumBy的惯用、一元版本会是什么样子?,haskell,monads,Haskell,Monads,如何获得有效容器的最大元素,其中计算要比较的属性也会触发效果 必须有更具可读性的做事方式,如: 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) 我使用重载版本而不

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

必须有更具可读性的做事方式,如:

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

我通常更喜欢*On版本的东西,它采用一个映射到可排序元素的函数,而不是*By版本的东西,它采用一个直接进行比较的函数。maximumByM与之类似,但有一个类似Monad m=>A->A->m Ordering->[A]->ma的类型,但这可能会迫使您为每个A重做效果,我猜这不是您想要的。我发现*On更多地与我想要做的事情和我想要的性能特征相匹配。

所以我对海龟一无所知;不知道这是否适合海龟生态系统的其他部分。但既然你在评论中说服了我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

我通常更喜欢*On版本的东西,它采用一个映射到可排序元素的函数,而不是*By版本的东西,它采用一个直接进行比较的函数。maximumByM与之类似,但有一个类似Monad m=>A->A->m Ordering->[A]->ma的类型,但这可能会迫使您为每个A重做效果,我猜这不是您想要的。我发现*On更经常与我想要做的事情和我想要的性能特征相匹配。

可以使用reducers软件包对折叠效果运行

我不确定它是否正确,但它利用了现有的组合器和实例,除了有界的a


可以使用reducers软件包在可折叠上运行效果

我不确定它是否正确,但它利用了现有的组合器和实例,除了有界的a


由于您已经熟悉Fold,您可能想了解FoldM,这与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在列表或其他可折叠容器上运行折叠。与Fold一样,FoldM也有一个应用实例,因此您可以将多个有效的Fold组合成一个,将每个有效的Fold的效果交错并组合其结果。

由于您已经熟悉Fold,您可能想了解FoldM,这与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在列表或其他可折叠容器上运行折叠。与Fold一样,FoldM也有一个应用实例,因此您可以将多个有效的Fold组合成一个,将每个有效的Fold的效果交错并组合其结果。

您的一元最大值的类型签名是什么?将非一元函数转换为一元函数通常很有用,特别是当所讨论的函数以某种有趣的方式是懒惰的时候。例如,ifM很有用,必须手工编写,而不是liftA3 if',因为它可以避免在两个分支中产生一种或另一种效果。但是maximumBy必须查看整个列表;所以没有什么有趣的懒惰需要保留。只需使用标准的一元组合器(如mapM)在前面完成所有效果,然后再进行纯计算。我可能会误解,但这种方法会允许严格的折叠运行而不会出现空间泄漏吗?@sevo Good point,这是另一个值得考虑的因素,可以手工制作一元版本。您的一元maximumBy的类型签名是什么?将非一元函数转换为一元函数通常很有用,特别是当所讨论的函数以某种有趣的方式懒惰时。例如,ifM很有用,必须手工编写,而不是liftA3 if',因为它可以避免在两个分支中产生一种或另一种效果。但是maximumBy必须查看整个列表;所以没有什么有趣的懒惰需要保留。只需使用标准的一元组合器(如mapM)在前面完成所有效果,然后再进行纯计算。我可能有点误解,但这种方法会允许严格的折叠运行而不会出现空间泄漏吗?@sevo Good point,这是另一个考虑因素,可能值得手动滚动一元版本。孤立实例是邪恶的,这个例子根本没有意义。你可能是说没什么;maxBound=Just maxBound根据我对你的另一个问题的回答,我推荐maxLengthIO=foldMap。fmap有限公司。f、 使用Data.Monoid.Inf.Finite。所需的体操动作要少得多,加上它使用了现代的可折叠习惯用法,已经取代了减速机包。请允许som

这一次我的大脑试图理解什么,但这看起来像是完美的答案!我不知道折叠式已经取代了减速机包!孤立的例子是邪恶的,而这个例子根本没有意义。你可能是说没什么;maxBound=Just maxBound根据我对你的另一个问题的回答,我推荐maxLengthIO=foldMap。fmap有限公司。f、 使用Data.Monoid.Inf.Finite。所需的体操动作要少得多,加上它使用了现代的折叠式成语,取代了减速机包装。请给我一些时间让我的大脑去理解,但这看起来是完美的答案!我不知道折叠式已经取代了减速机包!为什么不从Fold升级到FoldM?@dfeuer我不太明白这个问题。问题中的Fold.max来自foldl-Control.foldl,它提供了一种折叠类型,其折叠操作由Turtle重新导出,但也是一种FoldM类型。这两种方法都具有并行组合折叠的应用实例。应该可以用FoldM来表示有效的最大值。@dfeur听起来是个有趣的答案。你应该加上它!我就这么做了。虽然我返回了一个可能,但它与您的非常相似。为什么不从Fold升级到FoldM?@dfeur我不太理解这个问题。问题中的Fold.maximum来自foldl-Control.foldl,它提供了一种折叠类型,其折叠操作由海龟重新导出,但也是一种FoldM类型。这两种方法都具有并行组合折叠的应用实例。应该可以用FoldM来表示有效的最大值。@dfeur听起来是个有趣的答案。你应该加上它!我就这么做了。它和你的很相似,不过我可能会返回一个。很好!f对第一种模式中的效果进行延迟评估!尽管如此,这能保证吗?应用程序版本非常棒,但在组合函数的眼中,当结果相等时,它能破坏结果的稳定性吗?@sevo,我想我修正了类型错误。我还没试过编译它。稳定性是什么意思?因为Applicative可以并行运行效果,IO效果的完成顺序可能与它们在输入中出现的顺序不同。在这种情况下,在两个相等的元素中,应始终拾取输入中首先出现的元素。我想知道foldM是否有这个属性。@sevo,foldM的应用程序实例是完全确定的。它按从左到右的顺序运行一个元素的效果,然后移动到下一个元素。很好!f对第一种模式中的效果进行延迟评估!尽管如此,这能保证吗?应用程序版本非常棒,但在组合函数的眼中,当结果相等时,它能破坏结果的稳定性吗?@sevo,我想我修正了类型错误。我还没试过编译它。稳定性是什么意思?因为Applicative可以并行运行效果,IO效果的完成顺序可能与它们在输入中出现的顺序不同。在这种情况下,在两个相等的元素中,应始终拾取输入中首先出现的元素。我想知道foldM是否有这个属性。@sevo,foldM的应用程序实例是完全确定的。它按从左到右的顺序运行元素的效果,然后移动到下一个元素。