Trying to move from Prolog to Haskell.

It is necessary to make the calculation of arithmetic expression.

I write a recursive program similar to the program on Prolog. Since the Haskell list, unlike Prolog, all elements must be of the same type, using the [String] type. It is necessary to convert the arguments to the numerical representation, and the result of the calculation is back to the symbolic one.

The compiler does not skip.
Is something wrong with type declarations or is it a method error?

cc :: (String b) => [String] -> b cc (a:"*":b:t) = cc(c:t) where c=show(read a * read b) cc (a:"/":b:t) = cc(c1:t) where c1=show(read a / read b) cc (a:"-":t) = show(read a - read(cc t)) cc (a:"+":t) = show(read a + read (cc t)) cc (a:[]) = a cc [] = 0 

The error is as follows:

ERROR file:. \ E3.hs: 18 - Undefined class "String"

2 answers 2

First, notice what you have written in the function type declaration.

The error message actually states that there is no such class String . Indeed, String is not a class, it is just a data type, a list of characters. Therefore, the expression (String b) => ... does not make sense.

Probably, b should have a numeric type, you can use a specific one, for example, Double .

Thus, the function type will be the following: [String] -> Double .

Next, you have problems with the fact that the function does not always return a number, sometimes it returns a string. This is not so easy to fix, you need to make some changes to the logic of the program.

You need to reconsider the method of parsing such expressions, and use more appropriate Haskell programming techniques.

    In the ad type

     f :: (T a) => String => a 

    T is a type class (typeclass), String is a type, a is any type belonging to a type class T

    Int , Integer , Char , String are all types. Class types denote the type of certain "methods" (if expressed in terms of OOP), that is, it is something like interfaces or abstract classes.

    For example:

     class T a where f :: a -> Int g :: a -> Int gx = (fx) ^ 2 

    Here we declare a type class T such that for any type a belonging to T , there exists a function f type f :: a -> Int . Also to the variable of this type a you can apply the function g , which has already been implemented. Now we can make an already existing type (let it be a String ) an instance of the class T :

     instance T String where f = length 

    Thus, for the type String function f returns the length of the string:

     f "hello" -- вернёт 5 g "hello" -- вернёт (fx) ^ 2, или 25 

    The implemented function g can also be redefined in a class instance:

     instance T Int where fx = x gx = x + x 

    Now, back to your example. The cc function signature should look like this:

     cc :: [String] -> String 

    this means that the cc function takes a list of strings and returns a string. But generally using strings to represent different types of values ​​is a very bad idea (especially in Haskell, with its terrific type system). Usually, algebraic data types are used instead ( sealed classes in some object-oriented languages). I do not know what types of values ​​you have, but I will give an example with a list of different numbers ( Int and Float ) that need to be added together (I remind you that the operator (+) :: (Num a) => a -> a -> a in Haskell accepts two numbers of the same type belonging to the class of types Num - you can add either a whole with an integer, or a fractional with a fractional, but a whole with a fractional - you cannot):

     data MyNumber = MyInt Int | MyFloat Float mySum :: [MyNumber] -> MyNumber mySum = foldl myAdd (MyInt 0) myAdd :: MyNumber -> MyNumber -> MyNumber myAdd (MyInt x) (MyInt y) = MyInt $ x + y myAdd (MyInt x) (MyFloat y) = MyFloat $ (fromIntegral x) + y myAdd f@(MyFloat x) i@(MyInt y) = myAdd if myAdd (MyFloat x) (MyFloat y) = MyFloat $ x + y