Haskell Function Returning Empty List - haskell

I'm really an absolute newbie at Haskell, so I'm at a total loss as to how to debug some functions I wrote. When I call shuntingYard ["3+4"] I get back [], whereas I want to get back [34+]. Any and all help would be greatly, greatly appreciated.
import Char
isOperator :: Char -> Bool
isOperator x = elem x ['+','-','*','/','%','^','!','=','<','>']
associativityOf :: Char -> String
associativityOf x = if elem x ['+','-','*','/','%']
then "Left"
else "Right"
precedenceOf :: Char -> Int
precedenceOf x
| elem x "=<>" = 1
| elem x "+-" = 2
| elem x "*/%" = 3
| elem x "^!" = 4
| otherwise = 0
operatorActions :: [[Char]] -> [[Char]] -> [[Char]]
operatorActions stmt stack
| ( tokenAssoc == "Left" && tokenPrecedence <= stackPrecedence ) ||
( tokenAssoc == "Right" && tokenPrecedence < stackPrecedence ) =
[stackOper] : _shuntingYard stmt (tail stack)
| otherwise = _shuntingYard (tail stmt) ((head stmt) : stack)
where tokenAssoc = associativityOf (head (head stmt))
tokenPrecedence = precedenceOf (head (head stmt))
stackOper = if (not (null stack))
then (head (head stack))
else '='
stackPrecedence = precedenceOf stackOper
stackOperations :: [[Char]] -> [[Char]]
stackOperations stack
| ((not (null stack)) && (head (head stack)) == '(') =
error "Unbalanced parens."
| null stack = []
| otherwise = (head stack) : _shuntingYard [] (tail stack)
_shuntingYard :: [[Char]] -> [[Char]] -> [[Char]]
_shuntingYard stmt stack
| null stmt = stackOperations stack
| all isDigit (head stmt) = (head stmt) : _shuntingYard (tail stmt) stack
| isOperator (head (head stmt)) = operatorActions stmt stack
| (head (head stmt)) == '('=
_shuntingYard (tail stmt) ((head stmt) : stack)
| (head (head stmt)) == ')' = if (head (head stack)) == '('
then _shuntingYard (tail stmt) (tail stack)
else (head stack) : _shuntingYard stmt (tail stack)
| otherwise = _shuntingYard (tail stmt) stack
shuntingYard :: [[Char]] -> [[Char]]
shuntingYard stmt = _shuntingYard stmt []

As a general debugging technique, you can use the Debug.Trace module to find out which functions are being called and what their inputs are. Using look at the state of your algorithm after each step.
import Debug.Trace
-- Show arguments each time _shuntingYard is called
_shuntingYard :: [[Char]] -> [[Char]] -> [[Char]]
_shuntingYard stmt stack = traceShow (stmt, stack) $ __shuntingYard stmt stack
__shuntingYard stmt stack
| null stmt = stackOperations stack
{- etcetera -}
This prints:
(["3+4"],[])
([],[])
Hmm, you lost everything after the first call. Looking at the guards in __shuntingYard, it seems that the "otherwise" case gets called.
Maybe you wanted to call shuntingYard ["3", "+", "4"]?

Ok, let's just play through what happens when you call shuntingYard ["3+4"]:
It calls _shuntingYard ["3+4"] []
It goes through the guards of _shuntingYard:
null stmt = null ["3+4"] = false
all isDigit (head stmt) = all isDigit "3+4" = false as + is not a digit
isOperator (head (head stmt)) = isOperator '3' = false
Also false as '3' /= '('
Also false as '3' /= ')'
Since none of the guards matched, so we go into the default case and call _shuntingYard (tail stmt) stack = _shuntingYard [] []
This time the first guard(null stmt = null []) matches, so we call stackOperations [] and get [].

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)

If error, assign a specific value to variable

so I have this code fragment: where exponent = read (tail (dropWhile (/= '^') (head xs))) :: Int but there is a possibility of the list inside tail being empty, so that would mean there would be an error looking for a tail inside an empty list. Is there a way to do something like: if error: exponent = 1 ?
Here is the full function if it helps in any way :)
internalRepresentation :: [String] -> [(Int,Char ,Int)]
internalRepresentation xs
|null xs = []
|all isDigit (head xs) = (read (head xs), ' ', 0) : internalRepresentation (tail xs)
|head (head xs) == '-' = (-read (takeWhile isDigit (pos_mon)) :: Int, head (dropWhile isDigit (pos_mon)), exponent) : internalRepresentation (drop 1 xs)
|otherwise = (read (takeWhile isDigit (head xs)) :: Int, head (dropWhile isDigit (head xs)), exponent) : internalRepresentation (drop 1 xs)
where pos_mon = tail (head xs)
exponent = read (tail (dropWhile (/= '^') (head xs))) :: Int
Thanks for your time!
The functions read, head, and tail are partial which means that they can fail with an error as you have experienced. That is why many people avoid those functions. Personally, I would write it like this:
import Text.Read (readMaybe)
internalRepresentation' :: String -> (Int, Char, Int)
internalRepresentation' xs =
case reads xs of
[(n, "")] -> (n, ' ', 0)
[(n, x:xs')] ->
case readMaybe (drop 1 (dropWhile (/= '^') (x:xs'))) of
Just e -> (n, x, e)
Nothing -> error "Malformed exponent"
_ -> error "Malformed internal representation"
internalRepresentation :: [String] -> [(Int, Char, Int)]
internalRepresentation xs = map internalRepresentation' xs
You can probably avoid that ugly drop 1 (dropWhile (/= '^') (x:xs')) too if you constrain your input a bit more. But I'm not completely sure what this function is actually supposed to do, so I can't help much more.
For example, if you only want to parse strings that look exactly like 123^456 (without other characters in between), then you can write it like this:
internalRepresentation' xs =
case reads xs of
[(n, "")] -> (n, ' ', 0)
[(n, '^':xs')] ->
case readMaybe xs' of
Just e -> (n, '^', e)
Nothing -> error "Malformed exponent"
_ -> error "Malformed internal representation"

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)

Evaluating arithmetic string in Haskell- debugging

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]

Haskell beginner cannot match expected type

I need to write a program which decodes a list of four values, which can be either I or O into a list of [Either Bool Bool]. I know I have to use maybe, but I simply cannot wrap my head around it. Right now I am totally desperate because I simply cannot solve this problem.
An example input and output might look like this: [I,O,O,I] => [Left True, Right False]
Here is the current code I have:
module Blueprint where
import Prelude
import Data.Maybe
data Bit = O | I deriving (Eq, Show)
encode :: [Either Bool Bool] -> [Bit]
encode [] = []
encode l = case head l of
Left False -> [I, I] ++ encode (tail l)
Left True -> [I, O] ++ encode (tail l)
Right False -> [O, I] ++ encode (tail l)
Right True -> [O, O] ++ encode (tail l)
decode :: [Bit] -> Maybe [Either Bool Bool]
decode [] = Nothing
decode [x] = Nothing
decode l = if isNothing (decode (tail (tail l)))
then Nothing
else case head l of
I -> if l!!1 == I
then [Left False] ++ decode (tail (tail l))
else [Left True] ++ decode (tail (tail l))
O -> if l!!1 == I
then [Right False] ++ decode (tail (tail l))
else [Right True] ++ decode (tail (tail l))
and these are the errors I get:
Prelude> :load serialise
[1 of 1] Compiling Blueprint ( serialise.hs, interpreted )
serialise.hs:22:16:
Couldn't match expected type `Maybe [Either Bool Bool]'
with actual type `[Either Bool b0]'
In the expression: [Left False] ++ decode (tail (tail l))
In the expression:
if l !! 1 == I then
[Left False] ++ decode (tail (tail l))
else
[Left True] ++ decode (tail (tail l))
In a case alternative:
I -> if l !! 1 == I then
[Left False] ++ decode (tail (tail l))
else
[Left True] ++ decode (tail (tail l))
serialise.hs:22:33:
Couldn't match expected type `[Either Bool b0]'
with actual type `Maybe [Either Bool Bool]'
In the second argument of `(++)', namely `decode (tail (tail l))'
In the expression: [Left False] ++ decode (tail (tail l))
serialise.hs:23:16:
Couldn't match expected type `Maybe [Either Bool Bool]'
with actual type `[Either Bool b1]'
In the expression: [Left True] ++ decode (tail (tail l))
In the expression:
if l !! 1 == I then
[Left False] ++ decode (tail (tail l))
else
[Left True] ++ decode (tail (tail l))
In a case alternative:
I -> if l !! 1 == I then
[Left False] ++ decode (tail (tail l))
else
[Left True] ++ decode (tail (tail l))
serialise.hs:23:32:
Couldn't match expected type `[Either Bool b1]'
with actual type `Maybe [Either Bool Bool]'
In the second argument of `(++)', namely `decode (tail (tail l))'
In the expression: [Left True] ++ decode (tail (tail l))
serialise.hs:25:16:
Couldn't match expected type `Maybe [Either Bool Bool]'
with actual type `[Either a0 Bool]'
In the expression: [Right False] ++ decode (tail (tail l))
In the expression:
if l !! 1 == I then
[Right False] ++ decode (tail (tail l))
else
[Right True] ++ decode (tail (tail l))
In a case alternative:
O -> if l !! 1 == I then
[Right False] ++ decode (tail (tail l))
else
[Right True] ++ decode (tail (tail l))
serialise.hs:25:34:
Couldn't match expected type `[Either a0 Bool]'
with actual type `Maybe [Either Bool Bool]'
In the second argument of `(++)', namely `decode (tail (tail l))'
In the expression: [Right False] ++ decode (tail (tail l))
serialise.hs:26:16:
Couldn't match expected type `Maybe [Either Bool Bool]'
with actual type `[Either a1 Bool]'
In the expression: [Right True] ++ decode (tail (tail l))
In the expression:
if l !! 1 == I then
[Right False] ++ decode (tail (tail l))
else
[Right True] ++ decode (tail (tail l))
In a case alternative:
O -> if l !! 1 == I then
[Right False] ++ decode (tail (tail l))
else
[Right True] ++ decode (tail (tail l))
serialise.hs:26:32:
Couldn't match expected type `[Either a1 Bool]'
with actual type `Maybe [Either Bool Bool]'
In the second argument of `(++)', namely `decode (tail (tail l))'
In the expression: [Right True] ++ decode (tail (tail l))
Failed, modules loaded: none.
Right now anything that helps me solve this problem is welcome. I have tried this for the better part of the day and I simply can't solve it.
You need to put a Just before your case statement to convert those values to Maybe [Either Bool Bool] instead of just [Either Bool Bool]:
decode :: [Bit] -> Maybe [Either Bool Bool]
decode [] = Nothing
decode [x] = Nothing
decode l = if isNothing (decode (tail (tail l)))
then Nothing
else Just $ case head l of
I -> if l!!1 == I
then [Left False] ++ decode (tail (tail l))
else [Left True] ++ decode (tail (tail l))
O -> if l!!1 == I
then [Right False] ++ decode (tail (tail l))
else [Right True] ++ decode (tail (tail l))
But this won't solve all of it. You also have decode embedded in that computation, and its type is Maybe [Either Bool Bool], but to use ++ you need just the [Either Bool Bool] as ++ only works with lists. This is where the Maybe monad comes in handy:
decode [] = Nothing
decode [x] = Nothing
decode (x:y:rest) = do
end <- decode rest
let this = case (x, y) of
(I, I) -> Left False
(I, O) -> Left True
(O, I) -> Right False
(O, O) -> Right True
return (this : end)
The case statement here is really just a different way of writing your case/nested-ifs. I also used pattern matching to avoid all the uses of head, !!, and tail since those functions should usually be avoided (they call error instead of doing proper error handling using Maybe). The <- syntax for Maybe will exit the computation early if Nothing is returned, so end <- decode rest is the same as saying if isNothing (decode rest) then Nothing else <continue>. Then, instead of building the entire result in each branch of the case/ifs, just compute the single result from x and y, then build the result list at the end.

Resources