This code worked fine when it only took first.
I get this error after having added second.
Couldn't match expected type 'Char' with actual type 'String'
Expected type: [Char]
Actual type: [String]
In the first argument of `(++)', namely `first'
In the second argument of `(++)', namely `first ++ " " ++ last !! 0'
Which makes no sense to me because getArg is suppose to produce a list of string.
module Main where
import System.Environment
main :: IO ()
main = do
first <- getArgs
last <- getArgs
putStrLn ("Hello" ++ first ++ last !! 0)
getArgs returns a list of string, not a string. You could use it like this:
module Main where
import System.Environment
main :: IO ()
main = do
args <- getArgs
putStrLn ("Hello" ++ (args !! 0) ++ (args !! 1))
Of course, this is only a demonstration of how to use getArgs. In real program, you need to make sure you are given enough arguments before you actually use them.
You're trying to concatenate "Hello" which is a String to first which is a list of Strings.
I also don't understand why you're using getArgs twice. first == last.
Related
I want a program that takes lines and prints reverse when it encounters an empty line.
This is my code.
back :: IO()
back = do
line <- getLine
if (not $ null line) then do
mapM_ putStrLn (reverse line)
else return()
When I try to run this it gives an error.
* Couldn't match type `Char' with `[Char]'
Expected: [String]
Actual: [Char]
* In the second argument of `mapM_', namely `(reverse line)'
In a stmt of a 'do' block: mapM_ putStrLn (reverse line)
In the expression: do mapM_ putStrLn (reverse line)
|
6 | mapM_ putStrLn(reverse line)
| ^^^^^^^^^^^^
What is going wrong here?
line is a String. Since you use mapM_ putStrLn, it expects a list of strings, so mapM_ putStrLn :: [String] -> IO ().
It is not entirely clear if you want to reverse each line, or the lines itself. In case of the former, you can work with:
back :: IO()
back = do
line <- getLine
if not (null line) then do
putStrLn (reverse line)
back
else return()
in case of the latter, you can use recursion, and first call back recursively, and then print the line:
back :: IO()
back = do
line <- getLine
if not (null line) then do
back
putStrLn line
else return()
I was playing around with making custom list displays. The concept is really simple but I keep getting an IO() error. My code is:
displayList :: [Int] -> IO()
displayList [] = putStrLn ""
displayList (firstUnit:theRest) = putStrLn (show firstUnit ++ "\n" ++
displayList theRest)
The error code I am getting is:
• Couldn't match expected type ‘[Char]’ with actual type ‘IO ()’
• In the second argument of ‘(++)’, namely ‘(displayList theRest)’
In the first argument of ‘putStrLn’, namely
‘((show firstUnit) ++ (displayList theRest))’
In the expression:
putStrLn ((show firstUnit) ++ (displayList theRest))
The specific part of the line that is getting the error is the displayList theRest not the putStrLn ((show firstUnit) ++ part.
I think I understand what is happening which is that when displayList theRest is called in the line with the error it has the potential eventually after a few recursive calls to return an IO() type from the line displayList [] = putStrLn "" which is not supported as input in the putStrLn function. Would anyone know a way to solve this?
The Problem
The problem with your code is fairly obvious: as the compiler tells you, you're trying to concatenate a string (((show firstUnit) ++) with an IO() (the return type of your function)
Solution
The solution can take two paths: either you want a function that returns the whole string, and then prints it all in one, or just print it step by step recursively. What I mean is:
Return a string
displayList :: [Int] -> IO()
displayList = putStrLn . helper
where
helper :: [Int] -> String
helper [] = ""
helper (n:ns) = show n ++ "\n" ++ helper ns
This approach works fine, but I believe it's not tidy nor clear.
Better version
displayList' :: [Int] -> IO()
displayList' [] = putStrLn ""
displayList' (n:ns) = putStrLn (show n) >> displayList' ns
I think you can see how this version is easier to read. Also note that print :: Show a => a -> IO() works exactly as putStrLn . show
My print statement keeps throwing error, don't really understand what is going on.
import Data.ByteString.Lazy as BS
import Data.Word
import Data.Bits
readByte :: String -> IO [Word8]
readByte fp = do
contents <- BS.readFile fp
return $ Prelude.take 5 $ unpack contents
main :: IO ()
main = do
input <- readByte "DATA.BIN"
print "Byte 0: " ++ [input!!0]
Getting the below error:
Couldn't match expected type `[()]' with actual type `IO ()'
In the return type of a call of `print'
In the first argument of `(++)', namely `print "Byte 0: "'
Haskell is parsing print "Byte 0: " ++ [input!!0] as (print "Byte 0: ") ++ [input!!0], which is probably not what you intended. You might want
main :: IO ()
main = do
input <- readByte "DATA.BIN"
putStrLn $ "Byte 0: " ++ show (input!!0)
instead
I'm trying to read n lines of content into a List of Strings. I've tried several variations of the code below, but nothing worked.
main = do
input <- getLine
inputs <- mapM getLine [1..read input]
print $ length input
This throws the following error:
Couldn't match expected type `a0 -> IO b0'
with actual type `IO String'
In the first argument of `mapM', namely `getLine'
In a stmt of a 'do' block: inputs <- mapM getLine [1 .. read input]
In the expression:
do { input <- getLine;
inputs <- mapM getLine [1 .. read input];
print $ length input }
And
main = do
input <- getLine
let inputs = map getLine [1..read input]
print $ length input
throws
Couldn't match expected type `a0 -> b0'
with actual type `IO String'
In the first argument of `map', namely `getLine'
In the expression: map getLine [1 .. read input]
In an equation for `inputs': inputs = map getLine [1 .. read input]
How can I do this?
Use replicateM from Control.Monad:
main = do
input <- getLine
inputs <- replicateM (read input) getLine
print $ length inputs
In the spirit of give a man a fish / teach a man to fish: You could have found this yourself by searching Hoogle.
You have:
an action to perform of type IO String
a number of times to perform that action (type Int)
You want:
an action of type IO [String]
So you could search Hoogle for (IO String) -> Int -> (IO [String]). replicateM is the first hit.
One other way you can do this action is by using the pure replicate and the sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)
tool. Lets say first we will ask for a count and then ask for that many integers to print their sum on the terminal.
sumCountManyData :: IO ()
sumCountManyData = putStr "How many integers to sum..? "
>> getLine
>>= sequence . flip replicate getLine . read
>>= print . sum . map read
what's wrong with this code?
module Main where
import System.Environment
main :: IO ()
main = do
args <- getArgs
putStrLn ("Hello, " ++ args !! 0 ++ ", " ++ args !! 1)
putStrLn(add (read args !! 0) (read args !! 1))
add x y = x + y
Here are the error messages:
main.hs:8:15:
No instance for (Num String)
arising from a use of `add'
Possible fix: add an instance declaration for (Num String)
In the first argument of `putStrLn', namely
`(add (read args !! 0) (read args !! 1))'
In the expression: putStrLn (add (read args !! 0) (read args !! 1))
In the expression:
do { args <- getArgs;
putStrLn ("Hello, " ++ args !! 0 ++ ", " ++ args !! 1);
putStrLn (add (read args !! 0) (read args !! 1)) }
main.hs:8:25:
Couldn't match expected type `Char' with actual type `[Char]'
Expected type: String
Actual type: [String]
In the first argument of `read', namely `args'
In the first argument of `(!!)', namely `read args'
read args !! 0 should be read (args !! 0) and add x y = x + should be add x y = x + y. Also putStrLn takes a string only, so use print instead which also prints numbers.
However, seeing you are new to haskell. I rewrote part of your program to demonstrate a more haskellish way.
main = do
(arg0:arg1:restArgs) <- getArgs
putStrLn $ "Hello, " ++ arg0 ++ ", " ++ arg1
print $ add (read arg0) (read arg1)
add = (+)
I think it looks a bit cleaner now. Note that it's most often considered bad practice to use !!.
Just to add a little elaboration on the error messages and the solution given. Looking at the first error:
No instance for (Num String)
...
In the first argument of `putStrLn'
This might be a bit unclear. Have a look at the type signature for putStrLn:
putStrLn :: String -> IO ()
So, putStrLn is a function that takes a String and evaluates to an IO action. However you have directly tried to pass putStrLn some expression like (x + y), which is a number, and Strings are not numbers (in Haskell terms, its type signature is (Num t) => t).
The solution given above suggests using the print function instead:
print :: (Show a) => a -> IO ()
The difference between 'print' and 'putStrLn' is that print can take anything showable, which includes numbers.
Next up:
Couldn't match expected type `Char' with actual type `[Char]'
Expected type: String
Actual type: [String]
In the first argument of `read', namely `args'
This says the compiler expected a String as the first argument to read, but saw a list of Strings. Looking at the original code:
read args !! 0
In Haskell, function application has highest precedence, so the compiler basically reads your code like so:
(read args) !! 0
(note in particular that the application of read binds higher than the use of the !! operator). Hopefully it should be clear now that read has been applied to all of args.
As your intention seemed to be to read the first element of args, you need to use parentheses like so:
read (args !! 0)
Hope this makes the error messages a little more understandable!