Haskell 预期类型:[t0 a0] 实际类型:[a]

Haskell Expected type: [t0 a0] Actual type: [a]

data PossibleTuple a = Multiple (a, Int) | Single a

pack :: (Eq a) => [a] -> [a]
{-
...
-}

encode_modified' :: (Eq a) => [a] -> [PossibleTuple a]
encode_modified' [] = []
encode_modified' x = map (\x -> element x) (pack x)
    where
        element x
            | length x > 1 = Multiple (x, length x)
            | otherwise = Single x

我正在尝试这样做:

encodeModified "aaaabccaadeeee"
[Multiple 4 'a',Single 'b',Multiple 2 'c',
 Multiple 2 'a',Single 'd',Multiple 4 'e']

但是我得到这个错误:

    * Couldn't match type `a' with `t0 a0'
      `a' is a rigid type variable bound by
        the type signature for:
          encode_modified' :: forall a. Eq a => [a] -> [PossibleTuple a]
        at src/Lib.hs:117:1-54
      Expected type: [t0 a0]
        Actual type: [a]
    * In the second argument of `map', namely `(pack x)'
      In the expression: map (\ x -> element x) (pack x)
      In an equation for encode_modified':
          encode_modified' x
            = map (\ x -> element x) (pack x)
            where
                element x
                  | length x > 1 = Multiple (x, length x)
                  | otherwise = Single x
    * Relevant bindings include
        x :: [a] (bound at src/Lib.hs:119:18)
        encode_modified' :: [a] -> [PossibleTuple a]
          (bound at src/Lib.hs:118:1)
    |
119 | encode_modified' x = map (\x -> element x) (pack x)
    |                                             ^^^^^^   

为什么 pack x 需要类型 t0 a0xa0 类型,因此 pack x 将具有 [a0].

类型

所有类型似乎都匹配。 map 函数的输出是 PossibleTuple a0。我什至不知道 a0 t0 来自哪里。

Multiple 4 'a'

这与您定义的值构造函数不匹配。这是你定义的构造函数

data PossibleTuple a = Multiple (a, Int) | Single a

因此,要构建 Multiple,您应该 Multiple ('a', 4)。相反,如果你想要Multiple 4 'a',那么你的构造函数应该是

data PossibleTuple a = Multiple Int a | Single a

您认为 element 属于哪种类型?您在其参数上调用 length,这意味着您认为它需要一个列表作为输入。但是,您还将它映射到类型 [a] 的列表上,这意味着您认为它可以将任何类型 a 作为输入。这是类型不匹配。

同样你说你希望你的结果看起来像 [Multiple (4, 'a')],但是你的 element 函数永远不会产生这个结果。每个元组中的第一个元素是第二个元素的lengthlength 'a'是类型错误。

不过,我要做的第一件事是重新检查 pack 的类型。它不能用看起来非常相关的当前类型做任何事情。应该是Eq a => [a] -> [[a]]。之后您将有更多类型错误需要解决,从而更好地定义 element.

应该是pack :: Eq a => [a] -> [[a]].

这个函数已经存在,叫做group。它将列表的连续元素组合在一起,这些元素彼此相等。

然后 element 只需稍作调整即可工作,

    where
        element x
            | length x > 1 = Multiple (.... x, length x)
            | otherwise = Single (.... x)

同名出现在两个 .... 上。通常使用该函数是不受欢迎的,但在这里它通过构造是正确的。

或者您可以在模式匹配中使用 @ 模式,例如

    where
        element x@(h:_)
...........

如果您想知道,这种编码称为 运行 长度编码。


为了更容易看到发生了什么,如果我们用 plural 中的变量命名 lists,通常会在精神上有所帮助,比如使用 xs 用于 x 的列表(xs 应该像与“轴”押韵一样阅读):

encode_modified' :: (Eq a) => [a] -> [PossibleTuple a]
encode_modified' [] = []
encode_modified' x = -- map (\x -> element x) (pack x)
                     map (\xs -> element xs) (pack x)
  where
  element xs
    -- | length x > 1 = Multiple (x, length x)    -- length of "x"??
       | length xs > 1 = Multiple ( x , length xs)  -- no, of "xs"!!
                                   ---
       | otherwise = Single x
                          -----

并且(带下划线的)复数类型不匹配现在是不言而喻的。