Evaluating arithmetic string in Haskell- debugging - string

I'm attempting to take in a string, evaluate, and output the answer. For example: if the input is the string "2*(3+10)" then the output should be the int 26
At the moment, It isn't working. I'm having problems with white space. If there is white space in the code input, I get ***Exception: Char.digitToInt: not a digit ' '. If there is NO whitespace in the input i get *** Exception: Prelude.!!: index too large
import Data.Char
parseExpr :: String -> Int
parseExpr str = start(trim (str))
trim :: [Char] -> [Char]
trim xs = [ x | x <- xs, not (isSpace x)]
start :: [Char] -> Int
start xs = expression xs 0
expression :: [Char] -> Int -> Int
expression xs i
|(xs !! (((basic xs i (-1))!! 1)+1)) == '+' = (multiply xs ((basic xs i (-1))!! 1)) + (multiply xs ((basic xs (i+2) (-1))!! 0))
|(xs !! (((basic xs i (-1))!! 1)+1)) == '-' = (multiply xs ((basic xs i (-1))!! 1)) - (multiply xs ((basic xs (i+2) (-1))!! 0))
|otherwise = multiply xs i
multiply :: [Char] -> Int -> Int
multiply xs i
| (xs !! (((basic xs i (-1))!! 1)+1)) == '*' = (power xs ((basic xs i (-1))!! 0)) * (power xs ((basic xs (i+2) (-1))!! 0))
| (xs !! (((basic xs i (-1))!! 1)+1)) == '/' = (power xs ((basic xs i (-1))!! 0)) `div` (power xs ((basic xs (i+2) (-1))!! 0))
|otherwise = power xs i
power :: [Char] -> Int -> Int
power xs i
| (xs !! (((basic xs i (-1))!! 1)+ 1)) == '^' = (((basic xs i (-1))!! 0) ^ ((basic xs (i+2) (-1))!! 0))
|otherwise = (basic xs i (-1)) !! 0
basic :: [Char] -> Int -> Int -> [Int]
basic xs i pnum
| pnum > (-1) && (isDigit(xs !!(i+1))) = basic xs (i+1) (pnum*10 + (digitToInt(xs !! i)))
| isDigit(xs !! i ) && isDigit(xs !!(i+1)) = basic xs (i+1) (digitToInt (xs !! i))
| pnum > (-1) && not (isDigit(xs !!(i+1))) = [pnum, i] -- + digitToInt(xs !! i)
| xs !! i == '-' = [(-(basic xs (i+1)(-1)) !! 0) , i] -- may want to delete if add/sub can handle
| xs !! i == '(' = [(expression xs (i+1)), i]
| xs !! i == ')' = [(expression xs (i+1)), i] --This may not work here
| otherwise = [digitToInt (xs !! i), i]

Related

Where ist the infinity loop? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 13 days ago.
Improve this question
somebody care to tell me where the problem with this function is?
Something is wrong with this complex:
buildBoard :: String -> Board
buildBoard xs = buildBoard' ("+" ++ xs ++ "+") []
buildBoard' :: String -> [Cell] -> Board
buildBoard' [] _ = [[]]
buildBoard' xs result
|head xs == ',' && xs!!1 == ',' = buildBoard' (tail xs) (Empty:result)
|head xs == 'w' =
buildBoard' (drop (getFirstNonNumber 0) xs) (Piece White intConversion : result)
|head xs == 'b' =
buildBoard' (drop (getFirstNonNumber 0) xs) (Piece White intConversion : result)
|head xs == '/' && xs!!1 == ',' = buildBoard' (tail xs) (Empty:result)
|head xs == ',' && xs!!1 == '/' = buildBoard' (tail xs) (Empty:result)
|head xs == '+' && xs!!1 == ',' = buildBoard' (tail xs) (Empty:result)
|head xs == '+' && xs!!1 `elem` ['b','w'] = buildBoard' (tail xs) result
|head xs == ',' && xs!!1 == '+' = buildBoard2 (reverse (Empty:result))
|head xs == '+' = buildBoard2 (reverse result)
|otherwise = buildBoard2 (reverse result)
where intConversion = read [xs!!1..xs!!(getFirstNonNumber 0 -1)] :: Int
getFirstNonNumber num = if xs!!num `elem` [',','/'] then num else getFirstNonNumber num+1
separate :: Int -> [a] -> [[a]]
separate _ [] = []
separate n l
| n > 0 = take n l : separate n (drop n l)
| otherwise = []
buildBoard2 :: [Cell] -> Board
buildBoard2 = separate 9
some additional info about what Cell, Board etc is:
data Player = Black | White deriving Show
data Cell = Piece Player Int | Empty deriving Show
data Pos = Pos { col :: Char, row :: Int } deriving Show
type Board = [[Cell]]
Here, at least, is one:
getFirstNonNumber num = if ... then num else getFirstNonNumber num+1
You almost certainly meant that last call to be:
getFirstNonNumber (num+1)

How to solve Haskell parse error on input 'otherwise'

I have a function which returns a list of halves of palindromes found from the input list. It works if I use an if-statement on one row but I'd like to use guards. Guards give me a parse error. I read many cases giving this kind of error, but I didn't figure out my case. Here is the code:
palindromeHalfs :: [String] -> [String]
palindromeHalfs xs = map firstHalf (filter palindrome xs)
where
firstHalf :: String -> String
firstHalf ys | (length ys) `rem` 2 == 0 = take ((div (length ys 2)) ys
| otherwise = take ((div (length ys 2) + 1) ys
palindrome :: String -> Bool
palindrome str | str == reverse str = True
| otherwise = False
And the error:
palindromeHalfs.hs:6:20: error: parse error on input `otherwise'
|
6 | | otherwise = take ((div (length ys 2) + 1) ys
| ^^^^^^^^^
The function works if I replace
firstHalf ys | (length ys) `rem` 2 == 0 = take ((div (length ys 2)) ys
| otherwise = take ((div (length ys 2) + 1) ys
with
firstHalf ys = if (length (ys !! 0)) `rem` 2 == 0 then take ((div (length (ys !! 0)) 2)) ys
else take ((div (length (ys !! 0)) 2) + 1) ys
In my code the if-statement is one row, it didn't fit here. I'd appreciate if someone can tell me which is preferred, if or guards. And of course, why my guards do not work.
The parentheses are not balanced in
take ((div (length ys 2)) ys
As for style, guards are much preferred over if/else in cases where either may be used. Note also that even :: Integral a => a -> Bool is a function that exists; you don't have to invent it with rem.

How to use toUpper and toLower in Haskell without importing module Data.Char?

So I am trying to write my own functions without help from imports and i am struggling to have a function that works the same way.
Here is what I have.
toLower'' :: [Char]-> [Char]
toLower'' [] = []
toLower'' (x : xs)
| x `elem` ['a' .. 'z'] = toEnum (fromEnum x + 32) : toLower'' xs
| otherwise = x : toLower'' xs
toUpper'' :: [Char] -> [Char]
toUpper'' [] = []
toUpper'' (x : xs)
| x `elem` ['a' .. 'z'] = toEnum (fromEnum x - 32) : toUpper'' xs
| otherwise = x : toUpper'' xs
toLower'' is matching the lower-case characters instead of the upper case. (ToUpper'' works). Fixed:
toLower'' :: [Char]-> [Char]
toLower'' [] = []
toLower'' (x : xs)
| x `elem` ['A' .. 'Z'] = toEnum (fromEnum x + 32) : toLower'' xs
| otherwise = x : toLower'' xs

splitting strings in haskell programming

Hi i am trying to do a function input is a list of strings, and the output is again a list of all words occurring in the input.
for example input ["For example,", "love,", "hate."]
output ["For","example","love","hate"]
atm i have this. Any help would be appreciated. Also how can i remove the blank space with just one function and in linear time?
And not using any existing function
split' :: String -> [String]
split' [] = []
split' (x:xs)
| isBlank x = split' xs
| otherwise = waitForBlank (x:xs) : split' (drop (length (waitForBlank (x:xs))) xs)
isBlank :: Char -> Bool
isBlank x = if x == ' ' then True else False
waitForBlank :: String -> String
waitForBlank [] = []
waitForBlank (x:xs)
| isBlank x = []
| otherwise = x : waitForBlank xs
There's a cool one-line to perform what you need
["For example,", "love,", "hate."] >>= words
>>= has type (>>=) :: Monad m => m a -> (a -> m b) -> m b, which takes a function which returns a monadic structure and joins the result into the monadic structure.
If you want to implement words by yourself:
words' xs =
let
waitForBlank (acc, buff) [] = (acc ++ [buff], buff)
waitForBlank (acc, buff) (x:xs) =
if x == ' ' then
waitForBlank (acc ++ [buff], []) xs
else
waitForBlank (acc, buff ++ [x]) xs
in
fst (waitForBlank ([], []) xs)
Or with using (:) and reverse the result (for better performance):
words'' xs =
let
waitForBlank (acc, buff) [] = (reverse (buff : acc), buff)
waitForBlank (acc, buff) (x:xs) =
if x == ' ' then
waitForBlank ((reverse buff) : acc, []) xs
else
waitForBlank (acc, x:buff) xs
in
fst (waitForBlank ([], []) xs)

Structural Induction - (zip xs ys)!!n = (xs!!n, ys!!n)

Given n >= 0 and n < min (length xs) (length ys)
show that (zip xs ys)!!n = (xs!!n, ys!!n) with structural Induction over xs.
Is it even possible to do this in a clean way? I cant find any spots where I can use the Induction Hypothesis.
First, I'll give definitions of zip and !!:
zip :: [a] -> [b] -> [(a,b)]
zip [] [] = [] -- (zip-1)
zip (x:xs) (y:ys) = (x,y) : zip xs ys -- (zip-2)
zip _ _ = [] -- (zip-3)
(!!) :: [a] -> Int -> a
(x : _) !! 0 = x -- (!!-1)
(_ : xs) !! n = xs !! (n - 1) -- (!!-2)
Let xs, ys and n arbitrary. Now, suppose that n >=0 and n < min (length xs) (length ys). We proceed by induction on xs.
Case xs = []. Now we do case analysis on ys. In both cases, we have that there's no n >=0 and n < min (length xs) (length ys). So, this case is trivially true.
Case xs = x : xs'. We proceed by case analysis on ys.
Case xs = x : xs' and ys = []. Again, we have the theorem trivially true since there's no n such that that n >=0 and n < min (length xs) (length ys).
Case xs = x : xs' and ys = y : ys'. Now we do case analysis on n.
Case xs = x : xs', ys = y : ys' and n = 0. We have that
zip (x : xs') (y : ys') !! 0 = {by equation (zip-2)}
(x,y) : zip xs' ys' !! 0 = {by equation (!!-1)}
(x,y) = {by equation (!!-1) - backwards}
((x : xs') !! 0, (y : ys') !! 0).
Case xs = x : xs', ys = y : ys' and n = n' + 1.
zip (x : xs') (y : ys') !! (n + 1) = {by equation zip-2}
(x,y) : zip xs' ys' !! (n + 1) = {by equation (!!-2)}
zip xs' ys' !! n = {by induction hypothesis}
(xs' !! n , ys' !! n) = {by equation (!!-2) backwards}
((x : xs') !! (n + 1), (y : ys') !! (n + 1))
QED
Hope that this helps.

Resources