Jump to content

new to Haskell - trouble compiling

- - - - -

  • Please log in to reply
6 replies to this topic

#1
EGD Eric

EGD Eric

    Newbie

  • Members
  • Pip
  • 8 posts
Hi there, I'm new to Haskell, and I'm trying to figure out why this won't compile, I've looked it over, and I don't get it:



module Main where


ls = [1,2,3,4,5]

 

main = do printList ls

  putStr "last element: " --. (++ (last ls)) . (++"\n")

  putStr "2nd element:" --. (++ (ls !! 1)) . (++"\n")

  putStr "number of elements in the list: "-- . (++ length ls)

    

--reverse the list

  reverse ls

  putStrLn "Reverse List:"

  printList ls

  -- putStrLn "list reversed: " ls


  

printList::[list]->()

printList [list] = ()   

  i = 0

  putStr "[" 

  loop = do putStr list !! i

    i = i + 1

	if i > (length list) - 1 then --when reached end, put a newline then return

	  putStrLn "]" 

	else

	  putStr ","

	  loop 

	  



Gives me error:
exercises.hs:8:3: parse error on input `putStr'
[1 of 1] Compiling Main ( exercises.hs, interpreted )
Failed, modules loaded: none.

I'm not sure what's happening, putStr is a real function, is it not?

#2
Sysop_fb

Sysop_fb

    Programmer

  • Members
  • PipPipPipPip
  • 160 posts
  • Location:Missouri
That error you mentioned is I'm assuming coming from your improper indentation. Haskell uses indentation as a cue to parse sections of code. These forums along with some editors that don't convert tabs to spaces properly can sometimes cause your indentation to get messed up.
Here's an hpaste demonstrating what I was just talking about

demo :: hpaste ? Haskell Pastebin

You're going to have more problems though in your code but I'll leave it up to you to ask the question or figure it out on your own.
"The best optimizer is between your ears" - Michael Abrash
Saying you can optimize a program is like saying you understand how a program works on every level of every facet on a specific machines configuration.

#3
EGD Eric

EGD Eric

    Newbie

  • Members
  • Pip
  • 8 posts
Thanks for that, that was really helpfull. You were right though, I still have problems with my code.

Couldn't match expected type `b0 -> a0' with actual type `IO ()'
In the return type of a call of `putStr'
In the first argument of `(.)', namely `putStr "last element: "'
In a stmt of a 'do' expression:
putStr "last element: " . (++ (last ls)) . (++ "\n")

I'm only trying to append a string together. I've seen other code that uses this syntax before, that's why I'm using all the parentheses. Tried it with just '.' or just ++, but that didn't work.

I also have a question about my printlist function: I don't think I'm using the proper syntax. I've looked for examples, but oddly enough, I can't seem to find any where the functions are multilined.

module Main where


ls = [1,2,3,4,5]

 

main = do putStr "last element: " . (++ (last ls)) . (++"\n")

          putStr "2nd element:" . (++ (ls !! 1)) . (++"\n")

          putStr "number of elements in the list: " . (++ length ls)

          --reverse the list

          reverse ls

        --  putStrLn "Reverse List:"

        --  printList ls

       -- putStrLn "list reversed: " ls


  

--printList::[list]->()

--printList [list] =    

--  i = 0

--  putStr "[" 

--  loop = do putStr list !! i

--         i = i + 1

--	     if i > (length list) - 1 then --when reached end, put a newline then return

--	         putStrLn "]" 

--	     else

--	         putStr ","

--	         loop 

	  


		



#4
Sysop_fb

Sysop_fb

    Programmer

  • Members
  • PipPipPipPip
  • 160 posts
  • Location:Missouri
Well ++ is used to concatenate two lists which I'm sure you know but what last is pulling from the list ls is not a string but an Int. Haskell doesn't let you do stuff like that which other languages might let you get away with.

So to concatenate the strings you'd need to turn it into a string an easy way being to use show
"last element: " ++ show (last ls)

Also instead of concatenating a newline char on the end you can use putStrLn which automatically adds a newline char at the end.

Now for the dot and dollar sign operators: basically a dot is just letting you chain function calls, the $ is basically the anti-lisp for haskell it lets you avoid the use of parenthesis. I'm going to attach an actual write up done on another forum, it wasn't by me and I forgot the persons name but he/she explained it pretty well.

Anyway these all give the same output
putStrLn ("last element: " ++ show (last ls))
putStrLn $ "last element: " ++ show (last ls)
putStrLn . (++) "last element: " $ show (last ls)
putStrLn . (++) "last element: " $ show . last $ ls
putStrLn . ("last element: " ++) . show $ last ls
putStrLn . ("last element: " ++) . show . last $ ls
putStr . (++ "\n") . ("last element: " ++) . show . last $ ls


Quote

The '$' operator is for avoiding parenthesis. Anything appearing after it will take precedence over anything that comes before.

For example, lets say you've got a line that reads:

putStrLn (show (1 + 1))

If you want to get rid of those parenthesis, any of the following lines would also do the same thing:

putStrLn (show $ 1 + 1)
putStrLn $ show (1 + 1)
putStrLn $ show $ 1 + 1

The primary purpose of the '.' operator is not to avoid parenthesis, but to chain functions. It lets you tie the output of whatever appears on the right to the input of whatever appears on the left. This usually also results in fewer parenthesis, but works differently.

Going back to the same example:

putStrLn (show (1 + 1))

1. (1 + 1) doesn't have an input, and therefore cannot be used with the '.' operator.
2. 'show' can take an Int and return a String.
3. 'putStrLn' can take a String and return an IO ().

You can chain 'show' to 'putStrLn' like this:

(putStrLn . show) (1 + 1)

If that's too many parenthesis for your liking, get rid of them with the '$' operator:

putStrLn . show $ 1 + 1

Also this will work since you can turn + 1 into a function
putStrLn . show . (+ 1) $ 1

"The best optimizer is between your ears" - Michael Abrash
Saying you can optimize a program is like saying you understand how a program works on every level of every facet on a specific machines configuration.

#5
Sysop_fb

Sysop_fb

    Programmer

  • Members
  • PipPipPipPip
  • 160 posts
  • Location:Missouri
On your printlist function
If you want to define a variable in a function like that or a function you should put them in a where block. For indentation basically the do block needs to have everything aligned

printList::
[list]->()
printList
[list] =    
  putStr "[" 
  loop = do putStr list !! i
            i = i + 1
            if i > (length list) - 1 then --when reached end, put a newline then return
                 putStrLn "]" 
            else
                 putStr ","
                 loop
            where
            i = 0


That's a very imperative way of writing code. Haskell has pattern matching that lets you iterate through a list pretty easily.
The code below uses pattern matching to break down a list into a cons format. It wouldn't be hard to change it to do what you're trying to do with printList though.


printConsList [] = putStrLn "[]"
printConsList (x:xs) = do putStr . (++ " : ") . show $ x
                          printConsList xs



so when you call prinConsList with [1,2,3,4]
It's going to pattern match [1,2,3,4] against [] which won't match at first so it trickles down to (x:xs) which does match because [1,2,3,4] can also be portrayed as 1 : [2,3,4] so it assigns basically the head of the list to x and the tail of the list to xs and then runs the statements in the do block which the end being to call printConsList with the tail of the list supplied in it's argument. Eventually it'll just be an empty list or [].
"The best optimizer is between your ears" - Michael Abrash
Saying you can optimize a program is like saying you understand how a program works on every level of every facet on a specific machines configuration.

#6
EGD Eric

EGD Eric

    Newbie

  • Members
  • Pip
  • 8 posts
Woah, that's awesome, thanks! Might you also know what's wrong with my call to reverse?

Couldn't match expected type `IO a0' with actual type `Bool'
In a stmt of a 'do' expression: ls <= reverse ls
In the expression:
do { putStr "List: ";
printList ls;
ls <= reverse ls;
putStr "List: ";
.... }


main = do 

	   { 

		  putStr "List: ";

                  printList ls;

                  ls <- reverse ls;

		  putStr "List: ";

		  printList ls;

		  putStrLn ( "last element: " ++ show (last ls));

                  putStrLn ( "2nd element:"  ++ show(ls !! 1));

                  putStrLn ("number of elements in the list: " ++ show(length ls));

	   }  



#7
Sysop_fb

Sysop_fb

    Programmer

  • Members
  • PipPipPipPip
  • 160 posts
  • Location:Missouri
The single assignment operator '<-' is used for IO actions to assign the result of an IO action to a variable name like using getline to retrieve input from the user
name <- getLine
So even if you fixed that line by doing something like this
ls <- print $ reverse ls
You would still get an error message because what would be loaded into ls would be an IO or () action and printList doesn't accept that data type.

You can use let bindings or where bindings in do but as a caveat when using let bindings in a do block you don't need to use the in keyword.

main = do putStr "List: "
          printList ls
          let revls = reverse ls
          putStr "List: "
          printList revls
          putStrLn ( "last element: " ++ show (last revls))
          putStrLn ( "2nd element:"  ++ show(revls !! 1))
          putStrLn ("number of elements in the list: " ++ show(length revls))



You can use an in keyword if you want but you'll need to specify another do block, this below code does the same thing.
main = do putStr "List: "
          printList ls
          let revls = reverse ls in
              do putStr "List: "
                 printList revls
                 putStrLn ( "last element: " ++ show (last revls))
                 putStrLn ( "2nd element:"  ++ show(revls !! 1))
                 putStrLn ("number of elements in the list: " ++ show(length revls))


"The best optimizer is between your ears" - Michael Abrash
Saying you can optimize a program is like saying you understand how a program works on every level of every facet on a specific machines configuration.




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users