I would like to get codes from the user and insert it in a list, but the problem is when the user say that don't wanna insert more codes. I don't saved a list with the numbers because I'm using recursion to call the method again, so when I should return the list I don't have it.
insertCode :: [Integer]
insertCode = do
putStrLn "Code:"
code <- getLine
putStrLn "Another? (Y/N)"
if(resp == "Y" || resp == "y") then (read code::String->Integer):insertCode else --I don't know
I'm sorry for my stupids questions, I imagine that is obvious but I have a problem with functional programming
First of all, your type signature is wrong. insertCode uses the IO monad, so the type must be IO [Integer]. You are also missing the conversion of code from a String to an Integer (I use readLn to accomplish that; you were trying to convert code into a function, not an Integer) and you are missing a getLine to get the Y/N response from the user.
Once that is fixed, you might write something like the following:
insertCode :: IO [Integer]
insertCode = do
putStrLn "Code:"
code <- readLn
putStrLn "Another? (Y/N)"
response <- getLine
result <- if (response == "Y" || response == "y")
then insertCode
else return []
return (code : result)
This is a little verbose, but tries to be explicit about how the monad is used. Whether the user enters Y or N, code must be appended to a list extracted from a monad: either a list extracted from a recursive use of insertCode, or an explicit empty list.
Related
I found this code online, but it's not running.
main = do
xs <- getLine []
print xs
So how do I ask the user for list input in Haskell? I am new to Haskell, please explain when you answer. Thanks.
You do it e.g. like this:
main :: IO ()
main = do
xs <- getLine
let { ints :: [Int]
; ints = read xs
}
print $ take 2 ints
and you must type in the input in a valid list syntax, e.g.
[1,2,3]
Do take note, each line in a do-block must start at the same indentation level (unless explicit separators { ; } are used).
getLine is an IO action that produces a string, nothing else. You need to process that string once you receive it. As an example, here's an IO action that will parse an appropriate input into a list of Int values.
getIntList :: IO [Int]
getIntList = fmap read getLine
main = do
ints <- getIntList
print ints
There is a Read instance for lists, so the following works:
> read "[1,2,3]" :: [Int]
[1,2,3]
getIntList uses the Functor instance for IO to apply read to the string that getLine will produce; read's concrete type will be inferred from the type given to getIntList: since getIntList :: IO [Int], then fmap read :: IO String -> IO [Int], and so read :: String -> [Int] will be used.
I am trying to write a simple function which reads in one line at a time (which I know will be integers) and then stores them in to a list. For the life of me however, it seems like the list comes out to empty.
import System.IO
import Control.Monad
type Int2 = [Int]
valueTab = [] :: [Int]
app [ ] list = list
app (h:t) list = h:(app t list)
main :: IO ()
main = do
hSetBuffering stdout NoBuffering -- DO NOT REMOVE
-- Auto-generated code below aims at helping you parse
-- the standard input according to the problem statement.
input_line <- getLine
let n = read input_line :: Int
let value = [] :: [Int]
replicateM n $ do
input_line <- getLine
let pi = read input_line :: Int
hPutStrLn stderr (show input_line)
hPutStrLn stderr (show valueTab)
return $ app valueTab [pi]
-- hPutStrLn stderr "Debug messages..."
-- Write answer to stdout
--putStrLn input_line
return ()
So when I run this with
8
6
4
3 all on their own lines,
It prints 6, [], 4, [], 3 [].
Is this a problem with my printing, with my list declaration, with the way that I store them or? I have both value and valueTab to check whether it was a scope problem.
Note: The code is boilerplate code on a coding website that tests it on it's platform. Assume replicateM is just a loop that runs through the code x number of times.
It looks like you're doing a problem on codinggame.com. Other coding sites seem to do a better job with their Haskell templates, particularly for beginner exercises -- the template usually takes care of all the input and output, and you just need to supply the missing pure function. In contrast, codinggame.com's Haskell templates seem to assume the beginner has a pretty firm grasp of the IO monad, and leave out a lot of essential details (e.g., the fact that the result of the replicateM action should actually be bound to a variable) which you're expected to fill in.
The replicateM call in the original template probably looked something like:
replicateM n $ do
input_line <- getLine
let pi = read input_line :: Int -- maybe this line was there, maybe not
return ()
This expression creates a composite IO action that, when executed, will repeat the following subaction n times:
read a line, binding the string read to input_line
prepare to convert that line to an integer value pi (though this is never done because pi isn't used)
regardless of the string read, return "unit" (the value ()) as the result of the subaction
The value of the composite action is then a list of the values returned by the subactions. Since those were all units, the final value of the composite action is a list [(),(),()...()], with one () for each line read. However, because the value of this composite action is never bound to a variable (i.e., because there's no result <- ... before the replicateM expression), this list is thrown away.
So, this template provides a needlessly verbose method of reading n lines of input and doing nothing with them.
Fortunately, all you need to do to make this template do something useful is to have the subaction return a value that's useful (e.g., the integer pi) which will cause the composite action to return a list of the integers read, and then make sure you bind the resulting list to a variable using the <- notation.
In other words, you want to write:
main = do
...
pis <- replicateM n $ do
input_line <- getLine
let pi = read input_line :: Int
return pi
hPutStrLn stderr (show pis)
You won't need the helper function app, and you won't need to pre-declare a list valueTab to contain the result. The result is automatically produced by replicateM, and you just need to name it so you can use it.
The complete working program will look like:
import System.IO
import Control.Monad
type Int2 = [Int]
main :: IO ()
main = do
hSetBuffering stdout NoBuffering -- DO NOT REMOVE
-- Auto-generated code below aims at helping you parse
-- the standard input according to the problem statement.
input_line <- getLine
let n = read input_line :: Int
let value = [] :: [Int]
pis <- replicateM n $ do
input_line <- getLine
let pi = read input_line :: Int
return pi
hPutStrLn stderr (show pis)
-- hPutStrLn stderr "Debug messages..."
-- Write answer to stdout
return ()
I have 2 lists which I am trying to fill will items. While reading from stdin, depending on the value of one of the things read, I want to append to a different list. Example,
import Control.Monad(replicateM)
main = do
n <- getLine
let l1 = [], l2 = []
in replicateM (read n) (getLine >>= (\line ->
case line of "Yes" ->
-- do something with line
-- and append value of that thing to l1
"No" ->
-- do something else
-- append this value to l2
putStrLn line))
I realise the above code has syntax errors and such, but hopefully you can see what I am trying to and suggest something.
This is the answer I came up with
While we are at it, can someone explain why this gives me an infinite list:
let g = []
let g = 1:g
-- g now contains an infinite list of 1's
This is what I finally came up with:
import Control.Monad(replicateM)
import Data.Either
getEither::[String] -> [Either Double Double]
getEither [] = []
getEither (line:rest) = let [n, h] = words line
fn = read f :: Double
e = case heist of "Yes" -> Left fn
"No" -> Right fn
in e : getEither rest
main = do
n <- getLine
lines <- replicateM (read n) getLine
let tup = partitionEithers $ getEither lines :: ([Double], [Double])
print tup
Not sure how fmap could have been used in this instance
Here is a short ghci session that may give you some ideas:
> :m + Control.Monad Data.Either
> partitionEithers <$> replicateM 3 readLn :: IO ([Int], [Bool])
Left 5
Right True
Left 7
([5,7],[True])
The answer to your second question is that let is recursive; so the two gs in let g = 1:g are referring to the same in-memory object.
You are thinking in term of mutable variables: you are "initializing" l1,l2 to the empty list and then reasoning about updating them with longer lists. This design works fine in imperative programming, but not so simply in pure functional programming since it involves mutation.
Now, even in pure functional programming we have ways to simulate mutation, through monads. For instance, once can achieve mutation here through IORefs or StateT IO. In this case, though, is would be an unnecessarily complex way to solve the task.
You want to append data to form two lists. You want to use replicateM, which is fine. The point is that replicateM will build just one list, instead of two. The question now is: how can we create a list which is easily split into two?
A first ugly attempt is to generate a list of tagged values, i.e. a list of pairs:
case line of
"Yes" -> let value = ... in
return ("for l1", value)
"No" -> let value = ... in
return ("for l2", value)
Doing this would make replicateM produce a list such as
[("for l1", value1), ("for l1", value2), ("for l2", value3), ...]
which we can then split into two lists.
The use of strings for tags looks however a bit unelegant, since a boolean would suffice:
case line of
"Yes" -> let value = ... in
return (True, value)
"No" -> let value = ... in
return (False, value)
An even better approach would be to use the Either a b type:
case line of
"Yes" -> let value1 = ... in
return (Left value1)
"No" -> let value2 = ... in
return (Right value2)
The nice consequence of the above is that value1 and value2 can even be of different types. The previous snippets forced them to share their type: since we build a list of pairs each pair must have the same type. The new list is now instead of type [Either a b] where a is the type of values to be put in l1, and b that for l2.
Once you get a [Either a b] you want to split it in [a] and [b]. As #DanielWagner suggests in his answer, you can exploit partitionEithers for this.
I've been trying many different ways to do this in Haskell, and I can't for the life of me figure this out.
I want to get a list of names from the user, and if I know the length of the list (let's assume that is n), I want to prompt the user n times and ask for the i th item at the i'th time.
So far, I have this:
getinput a b
| a == b = []
| otherwise = input:getinput (a+1) b
where input = do
a <- getLine
return a
but I keep getting errors.
Strongly appreciate any help!
Problem with your code
The return type of input is IO String so you just can not append it to a list.
Similarly the return type of getinput (a+1) b is IO [String] and not just [String].
Here I have corrected your code
getinput a b | a == b = return []
| otherwise = do
i <- getLine
rest <- getinput (a+1) b
return (i:rest)
A better and more haskellish way
getinput2 n = sequence $ replicate n getLine
Satvik had a good answer, but your code is also 100% correct.
You can append an IO String to the beginning of a list, as long as all elements are of the same type -- so you end up with something that has the type [IO String]
All you need to do, with the code you've written, is apply it with sequence -- for example:
sequence $ getinput 0 4
getChar :: Int -> IO Char
getChar n = do
c <- getLine
return (c !! n)
The program must needs a number and a line and it will return char, but how do I catch exception, if the number is too big?
I tried like this but it doesnt seem to work
getChar n
= do
c <-getLine
| n>=0 && n < b
= return c !! n
| otherwise
= error "Too big number"
where
b = length c
This is not a homework, im trying to involve myself. Google didint give me useful answers
Couldn't implement catch in there. Examples?
You probably want to restructure things a bit as you've got IO mixed up in something it doesn't have to be. What about changing the signature to something like this?
getChar :: Int -> String -> Maybe Char
getChar n x | n < length x = Just (x !! n)
| otherwise = Nothing
Data.Maybe allows you to indicate that you are either going to return something (e.g. the length is within range) or Nothing (the length isn't within range). The function that calls getChar can then decide what to do with things. Data.Either provides a way of returning an error message with an error instead. From what I've seen (and I'm by no means an expert) exceptions are rarely used in Haskell, and choice types such as Either or Maybe are much more commonly used.
Now in the code that calls this, you can use pattern matching to see what happened e.g.
main :: IO ()
main = do
x <- getLine
let z = getChar' 5 x
case z of
(Just z) -> print $ "The 5th character is " ++ show z
Nothing -> print $ "The 5th character is out of range"
You can use the drop function to drop the first n characters of the line (drop will just give an empty result if there are fewer than n chars), and the listToMaybe function to turn a list to a Maybe (either Just c where c is the first element of the list, or Nothing if the list is empty):
import Data.Maybe (listToMaybe)
getchar :: Int -> IO (Maybe Char)
getchar n = do
line <- getLine
return . listToMaybe . drop n $ line
getChar' :: Int -> IO Char
getChar' n =
do
c <- getLine
if (n < length c)
then
return (c !! n)
else
getChar' n
You can do something like above. This is just an example though. But, since you are a beginner, it is strongly recommended not to play with IO and Monads. You can come to it after you get familiarized with pure functional concepts.