简体   繁体   中英

Haskell type signatures with different types

I'm trying to create a function that takes a list of items and returns a list of either A) tuples of the form (2, "X") if the item "X" appears twice consecutively, or B) the item itself if it is not adjacent to a duplicate.

Example:

encode ["A", "A", "A", "B", "C", "C", "B", "B", "B", "D"]
> [(3, "A"), "B", (2, "C"), (3, "B"), "D"]

What would the appropriate type signature be? I have tried this:

data listItem a = (Integer, a) | a
encode :: (Eq a) => [a] -> [listItem a]

But I get this error:

parse error in constructor in data/newtype declaration: (Integer, a) 

I peeked at the solution to this problem, which gave me this type signature:

data ListItem a = Single a | Multiple Int a
    deriving (Show)
encode :: Eq a => [a] -> [ListItem a]

But when using this simple test

encode [x] = [x]

I get an error:

Could not deduce (a ~ ListItem a)
from the context (Eq a)
  bound by the type signature for
             encode :: Eq a => [a] -> [ListItem a]
  at 99problems.hs:117:19-45
  `a' is a rigid type variable bound by
      the type signature for
        encode :: Eq a => [a] -> [ListItem a]
      at 99problems.hs:117:19
In the expression: x
In the expression: [x]

What is the right type signature for this problem?

The "99 Problems" set was, as I understand it, written for Prolog originally, and then translated to Lisp. It was then ... ah ... transliterated to Haskell. Unfortunately, things that make sense in Lisp don't always make so much sense in Haskell, so taking the problem descriptions too literally will get you into trouble. What the hint is telling you is that instead of trying to write a function producing a list like [(3, "A"), "B", (2, "C"), (3, "B"), "D"] , which is simply impossible in Haskell, you should aim to produce a list looking like [Multiple 3 "A", Single "B", Multiple 2 "C", Multiple 3 "B", Single "D"] .

The suggested type signature is correct; you just need to write code to match it.

Note

As I said, the 99 Problems set does not tend to be very Haskellian. It does not respect the usual idiomatic style of Haskell code at all , so you should not take it as a model for how to write Haskell code. For example, a Haskell programmer (or, for that matter, a sane Lisp programmer) probably would just produce a list of (Int,a) pairs, and not bother with that single/multiple nonsense that makes everything more complicated, less uniform, and very likely slower in a real application.

A couple other ways "99 Problems" tends to break the usual expectations of Haskell programming:

  1. It tends to put arguments in a different order than a Haskell programmer would. If a function takes a list and a number, a Haskell programmer will almost always put the number first and the list second; "99 Problems" tends to do it the other way around.

  2. Haskell programmers almost always use 0-based indexing for lists, arrays, etc. "99 Problems" seems to like 1-based indexing.

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