You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Haskell中编写符合指定签名的groupBy函数?

Implementing groupBy :: (a -> a -> Bool) -> [a] -> [[a]] for Equality or Strictly Increasing Subsequences

Got it, let's work through implementing this custom groupBy function in Haskell. First, let's make sure we're all on the same page with the requirements:

  • Function Signature: Must be exactly groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
  • Grouping Rules: The function should cluster elements based on the provided binary predicate:
    • When using (==) as the predicate, group consecutive equal elements together.
    • When using (<) as the predicate, group consecutive elements that form a strictly increasing subsequence.

Example Usage

Let's start with the examples given to clarify expected behavior:

-- Grouping equal elements with (==)
groupBy (==) [0, 0, 1, 1, 2, 2] == [[0, 0], [1, 1], [2, 2]]
groupBy (==) [0, 1, 2] == [[0], [1], [2]]

-- Grouping strictly increasing subsequences with (<)
groupBy (<) [1,2,3,2,3,4,1] == [[1,2,3], [2,3,4], [1]]
groupBy (<) [5,4,3,2,1] == [[5], [4], [3], [2], [1]]

The Implementation

Here's an efficient recursive implementation that meets all the requirements:

groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
groupBy _ [] = []
groupBy p (x:xs) = go x [x] xs
  where
    go lastElem current [] = [current]
    go lastElem current (y:ys)
      | p lastElem y = go y (current ++ [y]) ys
      | otherwise = current : go y [y] ys

How It Works

Let's break down the logic step by step:

  1. Edge Case Handling: If the input list is empty, we just return an empty list—no groups to form.
  2. Initialization: For a non-empty list, we start our grouping process with the first element x as the start of the first group, using the helper function go.
  3. Helper Function go:
    • It keeps track of three key things: the last element in the current group (lastElem), the current group itself (current), and the remaining unprocessed elements of the list.
    • When there are no elements left to process, we wrap up by returning the current group as the final entry in our result.
    • If the next element y satisfies the predicate with lastElem (e.g., lastElem < y for strictly increasing, or lastElem == y for equality), we add y to the current group and keep processing the rest of the list.
    • If the predicate isn't satisfied, we finalize the current group, add it to our result, and start a new group with y as the first element.

Testing It Out

Let's verify with one of the trickier examples:

  • For groupBy (<) [1,2,3,2,3,4,1]:
    • We start with lastElem = 1, current = [1], remaining list [2,3,2,3,4,1]
    • 1 < 2 is true → update to lastElem = 2, current = [1,2], remaining [3,2,3,4,1]
    • 2 < 3 is true → update to lastElem =3, current = [1,2,3], remaining [2,3,4,1]
    • 3 < 2 is false → add [1,2,3] to results, start new group with 2
    • Repeat the process for the remaining elements, ending up with [[1,2,3], [2,3,4], [1]]—exactly what we expect!

This implementation is flexible enough to work with any valid binary predicate, not just (==) and <, while sticking strictly to the required signature.

内容的提问来源于stack exchange,提问作者polebence

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:43:57