41
votes

I'm just learning Haskell and I was trying to write a simple program to eliminate the first n characters from a String. This is what I got:

cutString :: (Num n, String str) => n -> str -> str

cutString n str = case n of
        0 -> tail str
        n -> cutString (n-1) (tail str)

GHC gives me this error though, and I can't figure out why:

`String' is applied to too many type arguments
 In the type signature for `cutString':
 cutString :: (Num n, String str) => n -> str -> str
2
FYI: cutString = GHC.List.drop - vivian
Thanks! I just wanted to write my own implementation anyway in order to practice, I just started studying Haskell today - Husker14
Note to modern audiences: nowadays cutString would also require Eq in the context since it uses a literal pattern match. - Ben Millwood
@Ben Millwood, thanks for pointing that out. I was wondering why this example no longer works in 2021, even after adjustments from the answers below. Howerver (Num n, Eq n) solves the issue. - Andrea

2 Answers

54
votes

String is a type, not a typeclass, so you can (must) just use it as-is in the type signature.

cutString :: Num n => n -> String -> String
33
votes

For reference, older GHCs (i.e. 7.2.2 or earlier) used to give this rather more helpful error:

Type constructor `String' used as a class
In the type `(Num n, String str) => n -> str -> str'

Indeed that is exactly your problem: String is a type, and you are using it as a type class. A type class is a collection of types, rather than a single type, e.g. Integer and Double and Rational are all types belonging to the type class Num. Type classes appear to the left of => in types, where real types and type variables appear to the right of =>.