user2225227
user2225227

Reputation: 31

Haskell where type declaration

I'm new to Haskell and having trouble with the type system. I have the following function:

threshold price qty categorySize
    | total < categorySize = "Total: " ++ total ++ " is low"
    | total < categorySize*2 = "Total: " ++ total ++ " is medium"
    | otherwise = "Total: " ++ total ++ " is high"
    where total =  price * qty

Haskell responds with:

No instance for (Num [Char])
      arising from a use of `*'
    Possible fix: add an instance declaration for (Num [Char])
    In the expression: price * qty
    In an equation for `total': total = price * qty
    In an equation for `threshold':
     ... repeats function definition

I think the issue is that I need to somehow tell Haskell the type of total, and maybe associate it with the type class Show, but I don't know how to accomplish that. Thanks for any help.

Upvotes: 3

Views: 339

Answers (2)

comingstorm
comingstorm

Reputation: 26117

The problem appears to be that you need to explicitly convert between strings and numbers. Haskell will not automatically coerce strings to numbers or vice versa.

To convert a number for display as a string, use show.

To parse a string into a number, use read. Since read actually applies to many types, you may need to specify the type of the result, as in:

price :: Integer
price = read price_input_string

Upvotes: 3

Scott Olson
Scott Olson

Reputation: 3542

The problem is you define total as the result of a multiplication, which forces it to be a Num a => a and then you use it as an argument to ++ with strings, forcing it to be [Char].

You need to convert total to a String:

threshold price qty categorySize
    | total < categorySize   = "Total: " ++ totalStr ++ " is low"
    | total < categorySize*2 = "Total: " ++ totalStr ++ " is medium"
    | otherwise              = "Total: " ++ totalStr ++ " is high"
    where total    = price * qty
          totalStr = show total

Now, that will run, but the code looks a little repetitive. I would suggest something like this:

threshold price qty categorySize = "Total: " ++ show total ++ " is " ++ desc
    where total = price * qty
          desc | total < categorySize   = "low"
               | total < categorySize*2 = "medium"
               | otherwise              = "high"

Upvotes: 10

Related Questions