Haskell : Float to IO Float - haskell

I have a type problem with this function
type Store = [(String, Float)]
evalParser :: String -> Store -> Float -- Boring function who returns a Float
programme :: Store -> IO()
programme store = do
putStr "#EvmInteractif:$> "
instruction <- getLine
putStrLn (show instruction)
if (estCommande (instruction) == True) then
do
res <- evalParser instruction store
putStrLn "TODO: execution de la commande"
programme store
And at the line of res's affectation I have this error :
Couldn't match expected type IO Float' with actual typeFloat'
In the return type of a call of `evalParser'
In a stmt of a 'do' block: v <- evalParser expr store
Can someone tell me the rigth syntax please ?
Thanks

evalParser is pure, you don't need to use do notation to call it. To shimmy fix it, you could just wrap it in a return to stick it in the IO Monad:
res <- return $ evalParser instruction store
To avoid the wrapping/unwrapping altogether though, just don't treat it as an impure value from the start:
let res = evalParser instruction store

Related

How to use value from different type monad in Haskell

Honestly, I feel like this must have a dupe somewhere, but I couldn't find it even after searching .
Say I have the following code to simply get read a double from the user and echo it back:
import qualified Control.Monad.Except as E
import Text.Read(readMaybe)
data Error = ParseError String
| Default String deriving (Show)
type ThrowsError = Either Error
main = do
putStrLn "Enter your number: "
val <- getDouble
print val
parseString :: String -> ThrowsError Double
parseString val = maybe (E.throwError $ ParseError val) return
(readMaybe val :: Maybe Double)
getDouble :: ThrowsError Double
getDouble = getLine >>= parseString
This breaks in two places:
In main, putStrLn is type IO Double but getDouble is type ThrowsError Double.
In getDouble, getLine is type IO Double but parseString returns IO Double.
Essentially, I'd want to be able to extract the value out of the IO monad, apply computations on it, and put it back inside the appropriate monad. However, the bind function seems to expect the same monad types for input and output, so what I want to do doesn't work.
What's the way around it?
You don't need any transformers. parseString is a pure function, so to apply it to a monadic action you use fmap (aka (<$>)), not (>>=) as you have.
getDouble :: IO (ThrowsError Double)
getDouble = parseString <$> getLine
You would use (>>=) if parseString returned an IO something.

Stop program from crashing when entering not-numbers in a menu with numbered options

My search function works properly when the input is a number, but crashes when it is not. What can I add to my code to prevent that from happening?
searchAge = do
putStrLn "\n Please type the age of the person you're looking for: \n"
age <- getLine
input <- readFile $ "databas.txt"
putStrLn "\n Here are all the people that matches your search: \n"
let people = parse input
output = map personToString (filter (\p -> personAge p == read age) people)
in putStrLn (unlines output)
putStrLn "Let's get back to the search menu again!"
searchDatabase
Listen up, oh younger one,
as this is a maddening song.
Take a look and you will see
read :: String -> Int is wrong for ye.
Its type is wrong, its result is unknown;
if been used on a string like "frown".
But here is for the final hint
you're looking for readMaybe :: String -> Maybe Int.
The problem with read is that there is no notion of failure in its type signature:
read :: Read a => String -> a
What happens if we set a to Int and try to use it on the string "frown"? It will result in an exception:
ghci> read "frown" :: Int
*** Exception: Prelude.read: no parse
After all, what should it return? Anything from the domain of Int is a valid value.
Enter readMaybe :: Read a => String -> Maybe a. Now the potential error is covered in the type signature, and it does not result in an exception anymore:
ghci> import Text.Read
ghci> readMaybe "frown" :: Maybe Int
Nothing
ghci> readMaybe "15" :: Maybe Int
Just 15
We can wrap this in a new function called getNumber that repeatedly asks for an Int until the user actually provides one:
getNumber :: IO Int
getNumber = do
line <- getLine
case (readMaybe line :: Maybe Int) of
Just x -> return x
Nothing -> putStrLn "Please enter a number!" >> getNumber
You can then use it to get an Int instead of a String for your age:
searchAge = do
...
age <- getNumber
input <- readFile "databas.txt"
putStrLn "\n Here are all the people that matches your search: \n"
let people = parse input
output = map personToString (filter (\p -> personAge p == age) people)
in putStrLn (unlines output)

Read Strings from command line util one can be 'read' as a Float

I'm trying to write code that will prompt the user to enter a Float and will continue to do so until a valid float is entered.
I've tried the following approach:
getFloat :: Float
getFloat = do
input <- getLine
case (readMaybe input :: Maybe Float) of Just f -> f
Nothing -> do getFloat
But I'm getting the following error:
Main.hs:41:5:
Couldn't match type `IO b0' with `Float'
Expected type: IO String -> (String -> IO b0) -> Float
Actual type: IO String -> (String -> IO b0) -> IO b0
In a stmt of a 'do' block: input <- getLine
In the expression:
do { input <- getLine;
case (readMaybe input :: Maybe Float) of {
Just f -> f
Nothing -> do { ... } } }
In an equation for `getFloat':
getFloat
= do { input <- getLine;
case (readMaybe input :: Maybe Float) of {
Just f -> f
Nothing -> ... } }
Main.hs:42:56:
Couldn't match expected type `IO b0' with actual type `Float'
In the expression: f
In a case alternative: Just f -> f
Main.hs:43:60:
Couldn't match expected type `IO b0' with actual type `Float'
In a stmt of a 'do' block: getFloat
In the expression: do { getFloat }
I'm a beginner a would very much appreciate if someone could explain what am I missing here.
For the Just case, use -> return f instead of -> f.
And then just remove the type signature for getFloat. After it compiles, have ghci tell you what the type signature for getFloat is.
Complete code:
getFloat = do
input <- getLine
case (readMaybe input :: Maybe Float) of Just f -> return f
Nothing -> do getFloat
Update
You might be interested in this highly-polymorphic version of the loop:
{-# LANGUAGE NoMonomorphismRestriction #-}
import Text.Read
getItem = do
input <- getLine
case readMaybe input of
Nothing -> getItem
Just x -> return x
I have purposely written getItem without a type signature - this is something that GHC can infer and fill in for you. I've also used the NoMonomorphismRestriction pragma so that getItem remains polymorphic.
The idea is that getItem can be used for any type that can be read - Floats, Doubles, Strings, etc. The type used by readMaybe can be controlled by the caller in various ways. Here are some examples:
main = do
f1 <- getItem
f2 <- getItem
let r = f1 + f2 :: Float
print r
By forcing r to be type Float, f1 and f2 must also be Floats, and therefore getItem will try to parse a Float.
Here is another way to influence the type that readMaybe uses:
main = do
f <- getItem :: IO Float
i <- getItem :: IO Int
print $ f^i -- compute f raised to the i-th power
getFloat :: Float
This states that getFloat is a constant of type Float, which is not what you want.
getFloat :: IO Float
This instead states that getFloat is an IO action producing a Float.
Once this is fixed, then you need to add return in front of your f, as #ErikR already explained. The return turns the pure float value f into an IO action which produces it, without actually performing any IO.
Finally, you do not need the do in the last do getFLoat. The do syntax is useful to sequence IO actions: if you only have one, it is redundant.

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.

Passing a function in for processing a CSV file: type error

Problem: Process a CSV file and test a condition on it. Current code simply prints instead of testing for the condition.
Issue: Type inference fails. I do not follow why it fails.
Here's the code, less the import boilerplate.
--------------------------------------------------
has_empty_string :: [String] -> Bool
has_empty_string col =
any null col
----------------------------------------
get_hashrow :: [[String]] -> [String]
get_hashrow sheet =
-- looking at column 5
map (\row -> row !! 5) sheet
------------------------------
process_lines :: (String -> b) -> Handle -> IO ()
process_lines func inh = do
ineof <- hIsEOF inh
if ineof
then return ()
else do inpStr <- hGetLine inh
result <- func inpStr
putStrLn $ show result
process_lines func inh
------------------------------
process_lines_in_file :: (String -> b) -> FilePath -> IO ()
process_lines_in_file func filename =
do inh <- openFile filename ReadMode
process_lines func inh
----------------------------------------
test_csv_row :: String -> Bool
test_csv_row row =
has_empty_string ( get_hashrow ( readCSV row))
----------------------------------------
main :: IO ()
main = do
[filename] <- getArgs
process_lines_in_file test_csv_row filename
return ()
And here's the error:
Couldn't match expected type `b' against inferred type `IO a'
`b' is a rigid type variable bound by
the type signature for `process_lines' at content-hash-p.hs:29:28
In a stmt of a 'do' expression: result <- func inpStr
In the expression:
do { inpStr <- hGetLine inh;
result <- func inpStr;
putStrLn $ show result;
process_lines func inh }
In the expression:
if ineof then
return ()
else
do { inpStr <- hGetLine inh;
result <- func inpStr;
putStrLn $ show result;
.... }
(In the future, please include the import boilerplate.)
Type inference is not failing -- since you're not asking the compiler to do any type inference! However, type-checking is failing. Let's see why.
You claim process_lines :: (String -> b) -> Handle -> IO (). Experienced Haskeller's will already be shuddering at this type. Why? This type claims that its first argument can be any function at all which does something to a String. But this is an odd claim to make, since the return type of this function doesn't appear anywhere else in the type of process_lines -- meaning, we can call this function, but never use its result! Thanks to laziness, this means that the call will never actually happen.
So it's a weird type. Let's see if we can take the argument above and find out where it fails in your code; that should help point to the problem.
process_lines func inh = do
ineof <- hIsEOF inh
if ineof
then return ()
else do inpStr <- hGetLine inh
result <- func inpStr -- HERE
putStrLn $ show result
process_lines func inh
Take a look at the line marked HERE. This is the only occurrence of func in our implementation. According to the argument above, we can never use the output of func, yet here we seem to be using the output of func. What type are we using it at? Well, we're using it at an IO {- something -} type, since it's in a do-block; furthermore, since we bind result and then call show result, the {- something -} must be some type that we can call show on -- that is, a member of the Show class. So the type of func is not as unrestricted as String -> b; it's the more restricted Show b => String -> IO b. A similar argument applies to process_lines_in_file, so that its updated type ought to be process_lines_in_file :: Show b => (String -> IO b) -> FilePath -> IO ().
(Indeed, if you leave off the type signatures, type inference will infer exactly these types for you.)
Now that process_lines_in_file demands a function that does IO, we can no longer pass test_csv_row as-is. You can choose either to call process_lines_in_file (return . test_csv_row) filename in main or to change the implementation of test_csv_row to call return (which does the trivial IO action: no input or output, just do a pure computation and pretend it did IO).
With these changes, the code compiles.

Resources