Kapol
Kapol

Reputation: 6463

Why (String, Int) is expected instead of (Char, Int)?

I am completely lost why the following doesn't work:

takeRange :: Int -> (a,Int) -> [(a,Int)] -> [(a,Int)]
takeRange n elem list = dropWhile (\x -> snd x < snd elem) (takeWhile (\x -> snd x < (snd elem) + n) list)

seriesLargestProd :: String -> Int -> Int
seriesLargestProd "" _ = 0
seriesLargestProd _ 0 = 0
seriesLargestProd s n = maximum [foldl1 (*) $ map (read . fst) (takeRange n pair zipped)
                                | pair <- zipped, snd pair <= lastStartingIndex] 
                                    where zipped = zip s [1..]
                                          lastStartingIndex = (length s) - (n-1)

The error messages I get:

Couldn't match type `Char' with `[Char]'
    Expected type: (String, Int)
      Actual type: (Char, Int)
    In the second argument of `takeRange', namely `pair'
    In the second argument of `map', namely `(takeRange n pair zipped)'

Couldn't match type `Char' with `[Char]'
    Expected type: [(String, Int)]
      Actual type: [(Char, Int)]
    In the third argument of `takeRange', namely `zipped'
    In the second argument of `map', namely `(takeRange n pair zipped)'

If anyone's interested, this is supposed to be an answer to problem 8 of Project Euler.

Upvotes: 0

Views: 131

Answers (2)

bheklilr
bheklilr

Reputation: 54058

The function you're mapping read . fst has the type Read a => (String, b) -> a. So map (read . fst) :: Read a => [(String, b)] -> [a]. But zipped has the type [(Char, Int)], and takeRange returns the same type of list as its input.

As an aside, you could implement takeRange as

takeRange n elem list = take n $ drop (snd elem) $ list

You're doing extra work by counting the indices manually, and as @sepp2k mentions this would be even more idiomatic with pattern matching on the tuple.

Upvotes: 3

sepp2k
sepp2k

Reputation: 370212

Why a String is expected, when zip will clearly "disunite" the string into individual characters?

Because read takes a String. In order to convert a single digit to an integer, use digitToInt, not read (alternatively you could also use read [theChar] to create a single-character string and convert it, but there's no need for that here as digitToInt exists).

PS: Instead of snd x and snd pair, it would be more idiomatic to use pattern matching to name the elements of the pair individually.

Upvotes: 2

Related Questions