Trouble making simple function in haskell - haskell

I am having trouble trying to convert the following block of C code into Haskell.
void echo(int num){
if(num != 0)
print(num)
else
exit()
}
I just started learning Haskell, but I am pretty confused as to how such a simple function could be so difficult.

What makes it seem difficult in Haskell is that the type system forces you to separate these kinds of functions from those that do not alter the state of the machine, such as printing to the screen or exiting the program. In order to write a function like this you have to use the IO monad:
import System.Exit -- Need this for exitSuccess
-- v The () is like void
echo :: Int -> IO ()
echo n =
if n /= 0
then print n
else exitSuccess
As you can see, there's nothing inherently more complex about this definition in Haskell than in the C-style languages. You just have to import the module that contains the function used to exit, and you have to write your function to work in the IO monad. You can use this function in a program as
loop :: IO ()
loop = do
putStr "Enter a number: "
numStr <- getLine
echo (read numStr)
loop
main :: IO ()
main = loop
This short snippet of code will continuously prompt the user for a number, then echo it back unless they enter 0.
I mentioned at the beginning of this answer that the type system doesn't let you mix state altering code with non-state altering code. How does it do this? In this case, any function with a type signature that ends with IO a (where a can be anything) executes in the IO monad, and only in that monad context. So you can't do something like
doubler :: Int -> Int
double n = 2 * (echo n)
This won't type check! 2 * expects the next argument to be an Int, whereas echo n has the type IO (). Even if it had the type IO Int, this is not the same as or compatible with the type Int. If instead you had
doubler :: Int -> IO Int
doubler n = do
echo n
return (2 * n)
You could then use it as
loop :: IO ()
loop = do
putStr "Enter a number: "
numStr <- getLine
nDoubled <- doubler (read numStr)
putStr "Your number doubled is "
print nDoubled
loop
Obviously, this will echo the original number, or exit the program if it's 0, then print Your number doubled is <n> where <n> is the new number, and then repeat this process until a 0 is entered.

Related

Why do I get Parse error on input`:: here

I am trying to make a guess the number game.
`
main :: IO()
checkGuess :: (Integral a) => a -> Bool
checkGuess b = if b == 9 then return True
main = do
print "Guess the number?"
guess <- getLine
checkGuess guess
but I get parse error on input '::' at the function checkGuess
There are several things that are wrong here:
you do not define the function directly after you wrote the signature of the function. You thus should first write the signature, and then write its binding, strictly speaking this is not an error as #chi says, but it is nevertheless strongly recommended;
In Haskell indentation matters: entering and leaving an indentation level says that you start or end a code block, for example for a where clause;
your checkGuess is supposed to return a Bool, but with return True, you make it a Monad m => m Bool;
in Haskell an if ... then ... else ... without an else does not exist. That is logical since a function should always return something;
getLine has as type IO String, so guess has type String, not Int, Integer, so you can not use guess directly to compare with a number; and
as #Krantz pointed out, the print here should probably be a putStrLn, since otherwise we print a string literal, not the string content.
In general it looks like you are writing an imperative program in a (pure) function language. A quick fix is the following:
checkGuess :: (Eq a, Num a) => a -> Bool
checkGuess = (9 ==)
main :: IO()
main = do
putStrLn "Guess the number?"
guess <- readLn :: IO Int
print (checkGuess guess)

How to wrap char literal in IO monad in Haskell?

I know you're supposed to wrap up the operations you want to perform on a result in a monad rather than unwrap things from the monad.
What I can't find are any idiot-friendly examples of how to do that.
For example, I want to do something like this:
myFunction = do
c <- getChar
if (c == 'q')
then putStrLn "take action 1"
else putStrLn "take action 2"
But you can't compare a char literal to an IO Char directly.
GHCi version is 8.4.4.
Error Message:
[1 of 2] Compiling Lib ( /Users/jamesstrieter/hask-tink/src/Lib.hs, interpreted )
/Users/jamesstrieter/hask-tink/src/Lib.hs:66:18: error:
• Couldn't match expected type ‘IO char’ with actual type ‘Char’
• In the second argument of ‘(==)’, namely ‘'q'’
In the expression: x == 'q'
In an equation for ‘what2do’: what2do x = x == 'q'
• Relevant bindings include
x :: IO char
(bound at /Users/jamesstrieter/hask-tink/src/Lib.hs:66:9)
what2do :: IO char -> Bool
(bound at /Users/jamesstrieter/hask-tink/src/Lib.hs:66:1)
|
66 | what2do x = x == 'q'
| ^^^
Failed, no modules loaded.
The code you posted looks perfectly correct and functional.
do-notation is a way of working with value in monad.
c <- getChar within the do block binds c to the char inside the IO Char you get with getChar. You can compare c == 'q' just fine here because c is a plain char, not an IO Char.
To answer you direct question, you can use the return function to put a pure value into any monad, including IO, so return 'q' "wraps" the character literal 'q' into a monad. This isn't what you want in this case, the code you already have is what you are looking for.
But you can't compare a char literal to an IO Char directly.
Sure, but when you "bind" the result of the IO action it is no longer an IO Char but just a Char so that's why it works.
In more words:
Prelude> :t getChar
getChar :: IO Char
Prelude> c <- getChar
x
Prelude> :t c
c :: Char
One of the most important things to understand about the IO monad is that the expression m >>= f does not execute the action m, nor does it ever call the function f.
Instead, it just creates a new IO action that wraps both m and f, which, when executed, will finally execute m, extract the return value, and then execute the next action calculated on the spot by calling f with that value.
That's it. Your entire Haskell program is nothing but a DSL for building a single IO action that gets assigned to main, which the Haskell runtime will execute for you.
So when you write
-- Rewritten slightly for brevity
myFunction = do
c <- getChar
putStrLn (if (c == 'q')
then "take action 1"
else "take action 2")
this is desugared to
myFunction = getChar >>= (\c ->
putStrLn (if (c == 'q')
then "take action 1"
else "take action 2")
and what you are actually saying is "Build an IO action containing getChar and a function of type Char -> IO (), such that when this action is executed, it executes getChar and passes the resulting Char to the function to produce another IO action to be executed immediately."

how to return an integer value from function without passing any argument in haskell

I need one function which read a file and return the number of lines in that file but it will not take anything as an argument.I have written this code but i am getting the error that couldnt match type IO Int with Int.
I am calling this function from another function as
let r=row'
Help me to figure it out
Thanks`
row'::()->Int
row' ()=do
content<-readFile "sample.txt"
let line_file=lines content
return (length line_file)
The problem here is that readFile and return are IO functions, and any function that performs IO in Haskell has to denote this in its type. You could instead write your function as
row' :: IO Int
row' = do
content <- readFile "sample.txt"
let line_file = lines content
return (length line_file)
And this would compile just fine. This restriction in the type signature is there to ensure that any function that has side effects or can return different values for the same input is sectioned off by the type system. This can greatly help in reasoning about your code, since for a pure function, such as
countRows :: String -> Int
countRows content = length (lines content)
Can always be guaranteed to return the same result for the same input. Then you can use these "pure" functions in "impure" functions to perform the actual calculations, keeping all the "impure" side effects contained to a single location:
row'' :: IO Int
row'' = do
content <- readFile "sample.txt"
return (countRows content)
Now row'' doesn't do anything other than read the file and pass the contents to a function that actually performs the work of counting the lines in that file. You could even state this more simply using fmap as
row'' :: IO Int
row'' = fmap countRows $ readFile "sample.txt"
To use this function, you can do something like
main :: IO ()
main = do
putStrLn "Counting the number of rows in sample.txt"
r <- row''
putStrLn $ "There are " ++ show r ++ " row(s) in sample.txt"
But note that row'' must be called from another IO function, you can not use it as
-- THIS IS WRONG, WON'T COMPILE
doubleRows :: Int
doubleRows = rows'' * 2
-- THIS IS WRONG TOO
doubleRows' :: Int
doubleRows' = do
r <- rows''
return (r * 2)
because both of these examples would have to have the type IO Int instead, and the first one wouldn't compile even with the right type signature because IO Int * Int doesn't make any sense, you have to first "extract" the Int from IO Int using the bind syntax of r <-.

Function Type in Haskell

I am new to Haskell. I want to have a function in which I get an Int value from the user using
putStr "Please Enter Your Number : "
submit_ans<- getLine
then after a series of calculations returns another Int which will be used by another function that has called it. What is the type of the described function? should I use return function at the end?
thanks in advance!
Update #1
ok I updated the function as below:
myFunction :: Int -> IO Int
myFunction action = do
putStr "\tPlease Enter Your Number : "
submit_ans <- getLine
if action == 1
then do
myFunctionII read submit_ans
else do
putStrLn("\n")
it gives me this error:
*** Term : myFunction
*** Type : Int -> IO Int
*** Does not match : IO a
Just write your function, say g, as a pure calculation, of type Int -> Int. Then you use it in IO monad as
...
putStr "Please Enter Your Number : "
submit_ans <- getLine
let i = g (read submit_ans)
...
print i
edit: Any Haskell value is pure. Functions are pure. IO x is a pure Haskell value. But it describes an impure computation, which will be run by the system (say, when your compiled application is run). As part of its execution, it will execute your pure function.
putStrLn has type String -> IO () and it seems myFunctionII has type Int -> IO (), so the type of myFunction should be Int -> IO () since both branches of your if return an IO ():
myFunction :: Int -> IO ()
myFunction action = do
putStr "\tPlease Enter Your Number : "
submit_ans <- getLine
if action == 1
then myFunctionII (read submit_ans)
else putStrLn "\n"
Since you are performing an IO operation and you are returning an Int so my best guess would be IO Int but I can't tell for sure because you question is too vague to answer clearly.

Haskell Input Return Tuple

i wonder can a IO() function return tuple because i would like to get these out of this function as input for another function.
investinput :: IO()->([Char], Int)
investinput = do
putStrLn "Enter Username : "
username <- getLine
putStrLn "Enter Invest Amount : "
tempamount <- getLine
let amount = show tempamount
return (username, amount)
Please help.
Thanks.
IO in Haskell doesn't work like IO in the languages you're used to. All functions in Haskell must be pure: that is, if a function f is called with the argument x, there must be no difference between calling it once, twice, or a hundred times. Consider what this means for IO, though. Naïvely, getLine should have the type getLine :: String, or perhaps getLine :: () -> String. (() is the unit type, whose only value is (); it's sort of like a void type in a C-like language, but there is a single value of it.) But this would mean that every time you wrote getLine, it would have to return the same string, which is not what you want. This is the purpose of the IO type: to encapsulate actions. These actions are distinct from functions; they represent impure computation (though they themselves are pure). A value of type IO a represents an action which, when executed, returns a value of type a. Thus, getLine has type getLine :: IO String: every time the action is evaluated, a String is produced (by reading from the user). Similarly, putStr has type putStr :: String -> IO (); it is a function which takes a string and returns an action which, when run, returns no useful information… but, as a side effect, prints something to the screen.
You are attempting to write a function of type IO () -> ([Char], Int). This would be a function which took as input an action and returned a tuple, which is not what you want. You want an IO (String, Int)—an action which, when run, produces a tuple consisting of a string (which is a synonym for [Char]) and an integer. You're almost there with your current code, too! This is what you'll need instead:
investinput :: IO (String, Int)
investinput = do
putStrLn "Enter Username : "
username <- getLine
putStrLn "Enter Invest Amount : "
tempamount <- getLine
let amount = read tempamount
return (username, amount)
Notice that I've only made two changes (and removed a blank line). First, I've changed the type of the function, like I said above. Second, I changed show into read. The show function has the type Show a => a -> String: it is a function which takes anything which can be shown and produces a string representing it. You wanted read, which has the type Read a => String -> a: given a string, it parses it and returns some readable value.
The other thing you asked about is returning a tuple (String, Int) instead of an action IO (String, Int). There is no pure way to do this; in other words, there is no pure function IO a -> a. Why is this? Because IO a represents an impure action which depends on the real world. If we had such a function impossibleRunIO :: IO a -> a, then we would want it to be the case that impossibleRunIO getLine == impossibleRunIO getLine, since the function must be pure. But this is useless, as we would want impossibleRunIO to be able to actually interact with the real world! Thus, this pure function is impossible. Everything that enters IO can never leave. This is what return does: it is a function with, in this case1, the type return :: a -> IO a, which enables you to place pure values into IO. For any x, return x is an action which, when run, always produces x. This is why you have to end your do block with the return: username is a pure value you extracted from an action, and as such is only visible within the do block. You need to lift it into IO before the outside world can see it. The same is true of amount/tempamount.
And just for completeness's sake: there is some overarching theory behind this which ties it together. But it's not necessary at all for beginning Haskell programming. What I would recommend doing is structuring most of your code as pure functions which fold, spindle, and mutilate your data. Then construct a thin (as thin as possible) IO front layer which interacts with said functions. You'll be surprised how little IO you need!
1: It actually has a more general type, but that's not relevant for the moment.
Yeah, you're almost there but I think you want the signature:
investinput :: IO ([Char], Int)
... then from the calling function you can do something like:
main = do
(username, amount) <- investinput
....
I think you want to read tempamount rather than show though.
An IO function that produces a tuple would have type IO (a, b), in this case:
investinput :: IO ([Char], Int)
A signature of IO () -> ([Char], Int) would mean that the function takes a parameter of type IO () and produces a tuple from that, which is not what you want.
Generally there are no restrictions on the types an IO function (or a function in a different monad) can return, you can chose the types however you like.
The answer to your question about returning (String, Int) rather than IO (String, Int) is simple: you can't. Once you're in IO you're stuck there. That's part of what it means when people say that Haskell is a "pure" language.
What you want to do is similar to what you're already doing here with getLine. The type of getLine is IO String. When you write username <- getLine, you're in effect taking the String out of the IO String, but this is only possible because you're inside the do expression.
You can do exactly the same kind of thing with investinput as with getLine. Here's an example of how you could use investinput in your main function:
main = do
(name, amount) <- investinput
putStrLn $ name ++ " invested $" ++ show amount ++ "."
Since you mention liftM in a comment, here's a full working version that does the same thing using liftM and the reverse bind operator (=<<) instead of do notation:
import Control.Monad (liftM)
investinput :: IO (String, Int)
investinput = do
putStrLn "Enter Username : "
username <- getLine
putStrLn "Enter Invest Amount : "
amount <- liftM read getLine -- We can also use liftM to get rid of tempamount.
return (username, amount)
summary :: (String, Int) -> String
summary (name, amount) = name ++ " invested $" ++ show amount ++ "."
main = putStrLn =<< liftM summary investinput
This shows how you could use investinput with "another function which expects a tuple".

Resources