0

I have this function that receives a list of integers and should return a String

generateSTR :: [Int] -> String
generateSTR ([]) = ""  
generateSTR (x) = daux (x (maximum x) x "") 
  where daux ((x:xs) mh y:ys strdib)  
           | mh == 0 = daux xs mh ys (strdib ++ "-")
           | mh <= h = daux (xs mh ys (strdib ++ "*"))
           | mh > h  = daux (xs mh ys (strdib ++ " "))
           | mh == 0 && length(lh) == 0 = daux xs (mh-1) ys (strdib ++ "\n")
        daux ([] mh lh strdib)   = strdib

The problem is that I'm getting an error:

"Parse error in pattern: (x : xs)"

But I can't see what I'm doing wrong.

For sure It's a silly error, but I'm newbie in HASKELL and I think I'm going crazy!.

2
  • Lol I'm just going to be a jerk for a second and say don't capitalize HASKELL like that. It's just Haskell. :-) Commented Aug 6, 2016 at 8:45
  • daux looks more complicated than it needs to be. The third argument is always the same as the first, and is never actually used. Commented Aug 6, 2016 at 12:49

2 Answers 2

2

This Haskell syntax f x y z is not just a different syntax for what other languages write as f(x,y,z). It is equivalent to that, yes, but only in the sense it is also equivalent to f(z,y,x): you still need to make a distinction.

Haskell functions are usually written curried. That means, if f “accepts three parameters”, what it actually does is accept one parameter, then another, then another:

f x y z ≡ ((f x) y) z

In other words, f is a function whose result is a function, whose result is a function. Only the result of that third function is “the final result”. Hence, you obviously can't write it f (x y z) – that would be something completely different, namely f applied to the result of applying the function x to y and z.

Perhaps all of this sounds complicated, but you will find many situation where currying allows you to write extremely concise and powerful code, and otherwise you just don't need to worry about it... simply write no parentheses that don't actually group independent subexpressions!

Applied to your example – this is the correct way to write it:

generateSTR :: [Int] -> String
generateSTR [] = ""  
generateSTR x = daux x (maximum x) x ""
  where daux (x:xs) mh y:ys strdib
           | mh == 0 = daux xs mh ys $ strdib ++ "-"
           | mh <= h = daux xs mh ys $ strdib ++ "*"
           | mh > h  = daux xs mh ys $ strdib ++ " "
           | mh == 0 && length lh == 0  -- note: this actually doesn't work, `lh` is not in scope here.
                     = daux xs (mh-1) ys $ strdib ++ "\n"
        daux [] mh lh strdib   = strdib

If you've not come across the $ operator yet: it has the same effect as putting both sides of it in parentheses, i.e.

      daux xs mh ys $ strdib ++ "-"
   ≡ (daux xs mh ys) (strdib ++ "-")

...and as I said, (f x y z) w is actually the same as f x y z w, so in this case it's the same as daux xs mh ys (strdib ++ "-"). But not the same as daux (xs mh ys (strdib ++ "-")), which would instead mean you apply the function xs to mh, then ys etc., which of course doesn't work because xs is a list!

Sign up to request clarification or add additional context in comments.

Comments

2

Because of the outer parentheses, this line:

where daux ((x:xs) mh y:ys strdib)  

says that daux takes one parameter. Perhaps you meant:

where daux (x:xs) mh (y:ys) strdib

which says that it takes four parameters. Note the parens added around y:ys.

You'll also have to fix where you call daux in your main function, e.g.:

generateSTR (x) = daux (x (maximum x) x "") 
                       ^                  ^ - remove these

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.