Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell - "Type error in application": "unification would give infinite type"

Tags:

haskell

I'm beginning work with Haskell, but this equality check I'm attempting to make isn't working out.

I have a function, countLetter a [b] c, where a is a char, b is a list of chars and c is an int. (The type declarations passed through fine.) But I run into problems with this expression:

if a == head(b)

Gives me the following message:

Type error in application

*** Expression     : a == head b
*** Term           : a
*** Type           : [a]
*** Does not match : a
*** Because        : unification would give infinite type

My code in full, if it's needed, is this:

countLetter :: char -> [char] -> int

countLetter a [b] c = if null b

                       then []
                       else
                       if a == head(b)
                       then countLetter a tail(b) c+1
                    else
                    countLetter head(b) tail(b) c

Any help or advice would be greatly appreciated. Thank you.

like image 446
Sam Ofloinn Avatar asked Dec 16 '22 16:12

Sam Ofloinn


1 Answers

First of all, types in Haskell start with capital letters. If you use identifiers starting with lower case letters in a type signature, they're interpreted as type variables. So your type char -> [char] -> int is the same as a -> [a] -> b, which is not a sensible type for your function. Your want Char -> [Char] -> Int.

Secondly [] is not a valid value of type Int. Fixing your type signature should produce an error message that tells you this in less ambiguous terms.

It should then also tell you that null b is a type error because b is of type Char (the second argument of your function is of type [Char] and you've matched it against the pattern [b], binding b to the single Char contained in that list) and null takes a list, not a Char, as its argument.

To clarify the last point a bit:

The second argument to your function is a list. By writing [b] in your parameter list, you're matching that argument against the pattern [b]. In other words writing countLetter a [b] c = blabla is the same as writing:

countLetter a theList c =
    case theList of
        [b] -> blabla

So you're saying: "the second argument to the function must be a list with one single element and that element shall be called b". That is not what you want to be saying. What you want to be saying is "the second argument to the function (which, incidentally, is a list) shall be called b". For that you simply writie countLetter a b c = blabla.

Parameters of type list don't have to be denoted any differently than other types of parameters.

like image 116
sepp2k Avatar answered May 11 '23 00:05

sepp2k