简体   繁体   中英

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

I'm trying to do this:

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

but I get this error:

    * 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)
    |                                             ^^^^^^   

Why would pack x need to have the type t0 a0 ? x is of type a0 and thus pack x would have type [a0] .

All the types seem to match. The output of the map function is PossibleTuple a0 . I don't even know where the a0 t0 comes from.

Multiple 4 'a'

This does not match the value constructor you defined. This is the constructor you defined

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

So to construct Multiple , you should do Multiple ('a', 4) . Conversely, if you want to do Multiple 4 'a' , then your constructor should read

data PossibleTuple a = Multiple Int a | Single a

What type do you suppose element has? You call length on its argument, meaning you think it takes a list as input. However, you also map it over a list of type [a] , meaning you think it can take any type a as input. This is a type mismatch.

Similarly you say you hope that your result will look like [Multiple (4, 'a')] , but your element function can never produce this result. The first element in each tuple is the length of the second element, and length 'a' is a type error.

The first thing I would do is re-examine the type of pack , though. It can't do anything with its current type that seems very relevant. Probably it should be Eq a => [a] -> [[a]] . After that you will have more type errors to resolve, leading to a better definition of element .

It should be pack:: Eq a => [a] -> [[a]] .

This function already exists, it is called group . It groups together consecutive elements of a list, which are equal to one another.

Then element needs just a small tweak to work,

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

with the same name appearing on both .... s. Normally using that function is frowned upon but here it will be correct by construction.

Or you could use @ patterns in pattern matching, like

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

This encoding is known as run-length encoding, in case you were wondering.


To easier see what's going on, it usually helps mentally if we name the lists by variables in plural , like using xs for a list of x s ( xs is to be read like it rhymes with "axes"):

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
                          -----

and the (underscored) plurality type mis-matches are now self-evident.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM