2
votes

So I'm trying to create a helper function that does something else, but I can't even get past the helper function because I keep getting this error:

Couldn't match expected type ‘[Char]’ with actual type ‘Int -> [t -> t1]’
freqsHelper x = freqs (x (lowers x))
                                 ^

The lowers(x) is causing the issue. Here is my code:

lowers [] = 0
lowers (x:xs) 
    | isLower x == True = 1 + lowers xs
    | otherwise = lowers xs

count _ [] = 0
count x (y:ys)
    | x == y = 1 + count x ys
    | otherwise = count x ys

percent x y = x/y*100

freqsHelper x = freqs (x (lowers x))

freqs (x:xs) y = percent ((count (x (x:xs))) y) : freqs xs y
3
What is freqs intended to do?Carbon
Like Davislor and MathematicalOrchid I advise you to write the type declarations for every function you write in the future. It saves you a lot of time in the end, because compiler can tell where you have gone wrong early on. The type system is one of the nicest things in Haskell, so you should use it to your advantage. Writing the type declarations also help you if you have to do some type-driven programming. With InstanceSigs extension you can also write type declaration for your functions in any instance of type class.Severi Jääskeläinen

3 Answers

2
votes

You’d be well-advised to add type declarations for every top-level function. Let’s follow what the type deduction system is doing here when it tries to figure this out.

The problem is not with lowers, which takes a [Char] as its argument and returns an Int.

The freqsHelper x declaration has one argument, x, whose type we’ll call a while we try to figure it out. We’ll call the return type b. So, freqsHelper is a function of type a -> b.

It’s also equal to freqs (x (lowers x)). So, x, which has type a, must be a function which takes the result of lowers as its argument. We know that lowers is [Char] -> Int, so a must be a function of type Int -> t1, where t1 is some type we would need to deduce from freqs. However, x is also passed as the argument of lowers. Which expects [Char], not a function with one argument. So we already have a contradiction.

So, there’s your mismatch. In the definition of freqsHelper, you’re using x in a context where Haskell expects a string, but also in a context where x has to be some kind of function. I’m pretty sure there’s a bug in freqs as well, given that it calls a function of two numeric arguments with only one argument.

0
votes

Ah, I think I know what you're getting at. You're close. A couple things - if you're gonna do a division, you should do a fromIntegral to get back some kind of fractional.

percent :: (Fractional a) => Int -> Int -> a
percent x y = (fromIntegral x / fromIntegral y) * 100

I think your frequency is trying to get the frequency of something in a list, in which case you'll need a base case:

freqs [] y = []
freqs (x:xs) y = percent (count x y) (length y) : freqs xs y 

I think you can figure out the rest from here.

A few style hints - you can use a map for freqs:

freqs' x y = map (\a -> percent (count a y) $ length y) x

The compiler will probably do it for you, but you can explicitly call out length y:

freqs' x y = map (\a -> percent (count a y) len) x
    where len = length y
0
votes
freqsHelper x = freqs (x (lowers x))

Let's break this down.

lowers x

You call lowers with x as input, so x must be a string.

x (lowers x)

But you call x as a function, passing it the result of lowers as input. So x must be a function that takes an Int as input. (That sounds like a mistake...)

freqs (x (lowers x))

You call freqs with the output from calling the x function... so x must return a list of some kind?

At this point, the type checker is confused as to what the heck x is even supposed to be, so it gives up.

Perhaps you meant to pass x and lowers x as two separate arguments? In that case, you want

freqs x (lowers x)

By putting brackets around x (lowers x), you make the compiler think that x is a function you want to call, with lowers x as the argument. I doubt you meant to do that.

As a side note, if you add type signatures on each of the functions you've defined, you may get a clearer indication from the type checker as to which bit is actually wrong. (As it is, the type checker can see the types don't line up, but can't actually determine where the types deviate from what you intended — because it cannot read your mind to know what you intended...)