"For all" 语句 Haskell

"For all" statements in Haskell

我正在通过一些 Haskell 玩具问题建立舒适感,并且我编写了以下代码

multipOf :: [a] -> (Int, a)
multipOf x = (length x, head x)
gmcompress x = (map multipOf).group $ x

成功执行了以下操作

gmcompress [1,1,1,1,2,2,2,3] = [(4,1),(3,2),(1,3)]

现在我想要这个函数,而不是告诉我集合中的一个元素具有多重性 1,而不是让它一个人呆着。因此,改为给出结果 [(4,1),(3,2),3]。如果有一种方法可以说(在将列表变成一对中的一个期间或之后)对于多重性 1 的所有元素,只作为一个元素离开;否则,对。我最初的天真想法是执行以下操作。

multipOf :: [a] -> (Int, a)
multipOf x = if length x = 1 then head x else (length x, head x)
gmcompress x = (map multipOf).group $ x

但这不起作用。我想是因为 thenelse 子句有不同的类型,不幸的是你不能分段定义函数的(共同)域。我该如何解决这个问题?

BUT this doesn't work. I think because the then and else clauses have different types, and unfortunately you can't piece-wise define the (co)domain of your functions. How might I go about getting past this issue?

您的诊断是正确的; thenelse 必须具有相同的类型。严格来说没有 "getting past this issue,"。无论您采用何种解决方案,都必须在条件的两个分支中使用相同的类型。一种方法是设计一个自定义数据类型来编码您想要的可能性,然后使用它。像这样的东西会起作用:

-- | A 'Run' of @a@ is either 'One' @a@ or 'Many' of them (with the number
-- as an argument to the 'Many' constructor).
data Run a = One a | Many Int a

但说实话,我不认为这会给你带来任何好处。我会坚持使用 (Int, a) 编码,而不是使用这种 Run 类型。