No instance for Foldable arising from length inside lambda
Asked Answered
T

1

7

first question here and completely a noob on haskell, so please be kind with me :)

I was playing with the question number 6 of this haskell exercises

and in the end came to the solution (or something similar I hope) with this code

combinations gr lis = filter clean $ sequence $ replicate gr lis
where
    clean string
        | total > gr = False
        | otherwise = True
        where total = sum [ rpt c string | c <- string]
    rpt chr list = length $ filter (== chr) list

the part that i like to be highlighted is the function 'rpt' which counts the number of times a character is repeated in a string, for example: "aaba" -> [3313] (the 3 comes from the letter a, which repeates 3 times) "aaccva" -> [332213]

later on I tried to make the function with a lambda and a map resulting in this:

rpt chr list = map (\chr -> length $ filter (== chr)) list

and at first ghci told me to use FlexibleContext to allow this, but if I do then it yields:

<interactive>:7:1:
No instance for (Foldable ((->) [Char]))
  arising from a use of ‘rpt’
In the expression: rpt 'a' string
In an equation for ‘it’: it = rpt 'a' string

and here I'am stuck, I have not been able to understand what's happening... what is needed to fix this function?

Tocharian answered 16/11, 2016 at 20:54 Comment(3)
This is pretty good structurally for the beginner you say you are, you have a knack for thisHorick
As general advice in these situations, when you get a confusing error message, start adding type annotations stating what you think the types should be. This will significantly improve the error messages. In fact, it's usually good practice to provide type annotations for all top-level functions to catch these sorts of mistakes as soon as possible.Earthshaker
This is good for a beginner. A couple of notes: 1) consider clean string = total <= gr where ... since using guards or if-then-else to return true/false looks more complex than it needs to be 2) your algorithm for combinations looks correct but suboptimal: you generate many candidates, and you need to filter them out later. Consider this: you can pick k elements from x:xs by either skipping x (and taking all k elements from xs) or choosing x (and then taking only k-1 elements from xs).Bagwell
C
7

You likely are intending to filter over list, so to make your code work, you need to also add list as an argument of filter:

rpt chr list = map (\chr -> length $ filter (== chr) list) list

For beginners, I recommend ignoring GHCi's suggestion of FlexibleContexts. It often ends up producing error messages like the one you had (or other confusing ones like No instance for (Num (Int -> Bool))).

Cargian answered 16/11, 2016 at 20:58 Comment(3)
Proposal: the fix he actually wanted was to include list at the end of the mapped function (as in map (\chr -> length $ filter (== chr) list) list). Your code produces a list of functions; mine produces a list of numbers.Festa
@DanielWagner I think you are right. I'll amend the solution accordingly.Cargian
wow such simple solution... thank you @Cargian you've helped me a lot!Tocharian

© 2022 - 2024 — McMap. All rights reserved.