Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell syntax, parse errors for dummies

today I read a lot about Haskell but this formating is driving me crazy. I want to understand my basic errors as soon as possible so I can start coding normally. The function here should return a string that starts with the next "math Sign" example string (2sdwds+asd)+3 should return +asd)+3. Here is the code

getToNextSign :: String -> String 
getToNextSign str = do

let mathSigns = ['+' , '-' , '*' , '/' , '^' , ')']
let a = head str
if a `elem` mathSigns 
 then str
 else if tail str /= [] 
       then getToNextSign $ tail str
       else []

main = do
putStrLn $ getToNextSign "(2sdwds+asd)+3"

It gives me " parse error on input = ". I am also not sure about how exactly to call it in the main and do I really need the putStrLn function. I don't think I need it but I tried like 2874 different ways to write this and now I just gave up and need help.

like image 881
user3129475 Avatar asked Feb 21 '26 23:02

user3129475


2 Answers

Besides the improvement to formatting that Stephen Diehl provided, there are other improvements you can make. As Carl points out, you can replace the if-else if-else with guards, like so:

getToNextSign :: String -> String
getToNextSign str
  | a `elem` mathSigns = str
  | tail str /= []     = getToNextSign $ tail str
  | otherwise          = []
  where
    a = head str
    mathSigns = ['+' , '-' , '*' , '/' , '^' , ')']

When you're at it, you can also replace the head/tail with pattern matching, as in

getToNextSign :: String -> String
getToNextSign (c:cs)
  | c `elem` mathSigns = c:cs
  | not (null cs)      = getToNextSign cs
  | otherwise          = []
  where
    mathSigns = ['+' , '-' , '*' , '/' , '^' , ')']

and if you're gonna do pattern matching, you can just as well take it all the way.

getToNextSign :: String -> String
getToNextSign str = case str of
     c:_ | c `elem` mathSigns -> str
     c:[] -> []
     _:cs -> getToNextSign cs
  where mathSigns = ['+' , '-' , '*' , '/' , '^' , ')']

and when you do it like this, you realise that you haven't really handled the case when getToNextSign gets an empty list as an argument, which is perhaps something you want to do.

like image 158
kqr Avatar answered Feb 24 '26 15:02

kqr


Here is a simpler alternative to your problem using the Prelude list functions, dropWhile and elem, which has a type sig (a -> Bool) -> [a] -> [a]. It takes a function which will drop the elements from a list as long as the condition provided by the function is true.

Hence, your function can be rewritten as follows.

let getNextSign x = dropWhile  ( not . `elem` "+-*/^)" ) x

Try to avoid explicit recursion when possible and put them higher order functions to good use. And the Prelude has tons of list manipulation functions which come in handy all the time.

like image 22
Akaberto Avatar answered Feb 24 '26 16:02

Akaberto



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!