连续组合相似的元素

时间:2017-08-17 19:58:47

标签: haskell

我是Haskell的新手,这就是我想要做的事情: enter image description here

到目前为止只有编译错误:

groupElems :: Eq a => [a] -> [[a]]
groupElems [] = []
groupElems (x:xs) = 
    let (a,b) = span (<= x) xs
    in a : (groupElems b)

谢谢。

错误:

Could not deduce (Ord a) arising from a use of ‘<=’
from the context (Eq a)
  bound by the type signature for groupElems :: Eq a => [a] -> [[a]]

4 个答案:

答案 0 :(得分:8)

编译器说:

Could not deduce (Ord a) arising from a use of ‘<=’
from the context (Eq a)
  bound by the type signature for groupElems :: Eq a => [a] -> [[a]]

Haskell编译器的目的是说您使用<= x代码,但<=函数不是 Eq类型类的一部分:如果我们问<=来自哪里,我们会得到:

Prelude> :i (<=)
class Eq a => Ord a where
  ...
  (<=) :: a -> a -> Bool
  ...
    -- Defined in ‘GHC.Classes’
infix 4 <=

因此我们可以使用Ord类型类来解决问题:它意味着元素是有序的。但根据您的示例,这是您想要的。如果我们使用Ord a作为类型约束,例如:

groupElems :: Ord a => [a] -> [[a]]
groupElems [] = []
groupElems (x:xs) = 
    let (a,b) = span (<= x) xs
    in a : (groupElems b)

第二个问题是我们*在span列表上调用xsxs是列表的 tail 。这意味着我们不会考虑到头脑。我们可以使用别名@来更改此设置并处理整个列表xa

groupElems :: Ord a => [a] -> [[a]]
groupElems [] = []
groupElems xa@(x:_) = 
    let (a,b) = span (<= x) xa
    in a : (groupElems b)

我们将获得:

GHci > groupElems []
[]
GHci > groupElems [1,2]
[[1],[2]]
GHci > groupElems [1,2,2,2,4]
[[1],[2,2,2],[4]]
GHci > groupElems [1,2,3,2,4]
[[1],[2],[3,2],[4]]

请注意,最后一个测试用例不正确。这是因为32都满足<= 3谓词。

如果您想按相等进行分组,则应使用(==) :: Eq a => a -> a -> Bool函数:

groupElems :: Eq a => [a] -> [[a]]
groupElems [] = []
groupElems xa@(x:_) = 
    let (a,b) = span (== x) xa  -- use == instead of <=
    in a : (groupElems b)

然后产生:

GHci > groupElems []
[]
GHci > groupElems [1,2]
[[1],[2]]
GHci > groupElems [1,2,2,2,4]
[[1],[2,2,2],[4]]
GHci > groupElems [1,2,3,2,4]
[[1],[2],[3],[2],[4]]

答案 1 :(得分:3)

编译器说a必须是Ord类型类的实例,因为使用<=。所以你可以纠正你的代码:

groupElems :: Ord a => [a] -> [[a]]

但是,如果您仍然需要使用Eq,则可以使用==代替<=,代码就可以使用。

我还注意到,您的代码版本在[1, [], [3]]示例中返回了[1,2,2,3,3],因为您传递了xs而不是整个列表。

groupElems :: Eq a => [a] -> [[a]]
groupElems [] = []
groupElems all@(x:xs) =
    let (a,b) = span (== x) all
    in a : (groupElems b)

顺便说一下,Data.List模块中的group功能完全符合您的目标

答案 2 :(得分:2)

您正在约束您的功能,以便a必须属于班级Eq。但是,函数<=属于Ord类型类。尝试将函数注释更改为:

groupElems :: Ord a => [a] -> [[a]]

答案 3 :(得分:2)

我认为你要找的是Data.List.group;

Prelude> Data.List.group [1,2,2,2,4]
[[1],[2,2,2],[4]]