How to print out bytes from binary file in Haskell? - haskell

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

Related

digitToInt, wrong datatypes and Unknown Exceptions

I earlier posted almost the same code where I created a lot of errors with lines I didn't even need. previous post
Now I took away the type signatures and my problems were reduced to 3.
And maybe now I might be able to explain what my problems are.
What ghci shows:
C:\Users\MATZE\Desktop\star.hs:8:25:
Couldn't match expected type `IO b0' with actual type `Int'
In the return type of a call of `digitToInt'
In a stmt of a 'do' block: temp <- digitToInt n
In the expression:
do { temp <- digitToInt n;
if (((c < 0) && (temp < 6) && (temp > 0))
|| (bs !! c >= temp)) then
do { return temp }
else
do { putStrLn "Ung\252ltige Eingabe";
.... } }
C:\Users\MATZE\Desktop\star.hs:20:66:
Couldn't match expected type `Int' with actual type `[Char]'
In the second argument of `(!!)', namely `l'
In the first argument of `replicate', namely `(bs !! l)'
In the second argument of `($)', namely
`replicate (bs !! l) (" *")'
C:\Users\MATZE\Desktop\star.hs:36:17:
Couldn't match type `IO' with `[]'
Expected type: [()]
Actual type: IO ()
In the return type of a call of `putStrLn'
In a stmt of a 'do' block:
putStrLn ("#Spieler " ++ show (pl - 1) ++ "hat gewonnen!")
In the expression:
do { putStrLn ("#Spieler " ++ show (pl - 1) ++ "hat gewonnen!") }
When I try to load this:
import Data.Char
board = [5,4,3,2,1]
--getMove :: [Int] -> Int -> IO Int
getMove bs c = do
n <- getChar
if isDigit n then do
temp <- digitToInt n
if (((c<0) && (temp<6) && (temp > 0))|| (bs!!c >= temp)) then do
return temp
else do
putStrLn "Ungültige Eingabe"
getMove bs c
else do
putStrLn "Ungültige Eingabe"
getMove bs c
--drawBoard :: [Int] -> Int -> String -> IO String
drawBoard bs l = do
putStrLn (show ((l + 1)++":" ++ (concat $ replicate (bs!!l) (" *") )))
if l < 3 then do
drawBoard bs (l + 1)
else do
putStrLn "\n"
--mainloop :: [Int] -> Int -> IO()
mainloop bs pl = do
line <- (getMove bs (-1))-1
number <- getMove bs line
b1s <- take line bs ++ [ ((bs!!line) - number) ] ++ drop (line + 1) bs
drawBoard b1s 0
if ((sum b1s) /= 0) then do
mainloop b1s ((pl `mod` 2) + 1)
else do
putStrLn ("#Spieler "++ show(pl -1)++"hat gewonnen!")
--main :: IO()
main = do
mainloop board 1
Why is there a problem with the digitToInt ?
Why does ghci think "l" is a [char] ?
And what does the last Exception even mean.
The arrow in do notation binds the results of a monadic computation, so
do ...
temp <- digitToInt n
...
expects digitToInt n to have a monadic type, IO a in your case. Instead, the way to bind pure values is with let:
do ...
let temp = digitToInt n
...
The second error has to do with the type of l, which apparently is inferred to be String (a.k.a. [Char]). First of all, I recommend that you uncomment your type signature, to make sure that everything has the type that you think it does. In this case the signature for drawBoard should have one fewer argument,
drawBoard :: [Int] -> Int -> IO ()
The actual reason for the error is the mismatched parentheses show ((l + 1)++":"++..., here you concatenate (l + 1) with a string. You probably meant to write show (l + 1)++":"++....
The third error is similar to the first, you should write
let b1s = take line (bs ++ [ ((bs!!line) - number) ] ++ drop (line + 1) bs)
instead of using an arrow.
Finally you are trying to use ...-1 to subtract from a monadic computation that returns a number. You first need to bind the result of the computation, and then subtract 1. Or you can use fmap/liftM to do this.
As a stylistic suggestion: all of your code lives in the IO monad, while much of it doesn't have to. For example, you can draw a board to a String, and then print it in one go.

getArgs expecting [char] instead of [string]

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.

Couldn't match expected type `IO b0' with actual type `[a0]'

I'm new to haskell guys. I'm trying to write a gcd executable file.
ghc --make gcd
When I compile this code I'm getting the following error.
Couldn't match expected type `IO b0' with actual type `[a0]'
In a stmt of a 'do' block:
putStrLn "GCD is: " ++ gcd' num1 num2 ++ "TADA...."
In the expression:
do { putStrLn "Hello,World. This is coming from Haskell";
putStrLn "This is the GCD";
putStrLn "Frist Number";
input <- getLine;
.... }
In an equation for `main':
main
= do { putStrLn "Hello,World. This is coming from Haskell";
putStrLn "This is the GCD";
putStrLn "Frist Number";
.... }
I don't understand where my problem is... Here is my code.
gcd' :: (Integral a) => a -> a -> a
gcd' x y = gcd' (abs x) (abs y)
where gcd' a 0 = a
gcd' a b = gcd' b (a `rem` b)
main = do
putStrLn "Hello,World. This is coming from Haskell"
putStrLn "This is the GCD"
putStrLn "Frist Number"
input <- getLine
let num1 = (read input)
putStrLn "Second Number"
input2 <- getLine
let num2 = read input2
putStrLn "GCD is: " ++ gcd' num1 num2 ++ "TADA...."
All I know is that read helps me convert my string into an int.
First, you need parentheses,
putStrLn ("GCD is: " ++ gcd' num1 num2 ++ "TADA....")
or infix function application ($):
putStrLn $ "GCD is: " ++ gcd' num1 num2 ++ "TADA...."
Without that, the line is parsed as
(putStrLn "GCD is: ") ++ gcd' num1 num2 ++ "TADA...."
and the concatenation of the IO-action putStrLn "GCD is: " with a String is what causes the - somewhat cryptic, before one has enough experience - type error.
From the context in that the line appears - in an IO-do-block - it must have type IO b for some b. But the type inferred from the application of (++) is [a] for some type a. These types cannot be matched, and that's what the compiler reports.
Note that after fixing that, you also need to convert the result of gcd' to a String,
putStrLn $ "GCD is: " ++ show (gcd' num1 num2) ++ "TADA...."
or you'll see another type error.
From the comment
To make my program look nicer. Is there a way that the input area is right next to the statement instead of a line down?
In general, yes. Instead of using putStrLn which appends a newline to the output string, use putStr which doesn't.
putStr "Second Number: "
input2 <- getLine
In interactive mode (ghci), that works well. stdout is not buffered there. For compiled programmes, stdout is usually line-buffered, that means it will not output anything until a newline shall be output or the buffer is full.
So for a compiled programme, you need to explicitly flush the output buffer,
import System.IO -- for hFlush
putStr "Second Number: "
hFlush stdout
input2 <- getLine
or turn off buffering altogether
import System.IO
main = do
hSetBuffering stdout NoBuffering
...
But at least the latter method used to not work on Windows (I'm not sure whether that's fixed, nor am I absolutely sure that hFlushing works on Windows).

How to do something with data from stdin, line by line, a maximum number of times and printing the number of line in Haskell

This code reads the number of lines to process from the first line of stdin, then it loops number_of_lines_to_process times doing some calculations and prints the result.
I want it to print the line number in "Line #" after "#" but I don't know how to obtain it
import IO
import Control.Monad (replicateM)
main :: IO ()
main = do
hSetBuffering stdin LineBuffering
s <- getLine
let number_of_lines_to_process = read s :: Integer
lines <- replicateM (fromIntegral(number_of_lines_to_process)) $ do
line <- getLine
let number = read line :: Integer
result = number*2 --example
putStrLn ("Line #"++": "++(show result)) --I want to print the number of the iteration and the result
return ()
I guess that the solution to this problem is really easy, but I'm not familiar with Haskell (coding in it for the first time) and I didn't find any way of doing this. Can anyone help?
You could use forM_ instead of replicateM:
import IO
import Control.Monad
main :: IO ()
main = do
hSetBuffering stdin LineBuffering
s <- getLine
let number_of_lines_to_process = read s :: Integer
forM_ [1..number_of_lines_to_process] (\i -> do
line <- getLine
let number = read line :: Integer
result = number * 2
putStrLn $ "Line #" ++ show i ++ ": " ++ show result)
Note that because you use forM_ (which discards the results of each iteration) you don't need the additional return () at the end - the do block returns the value of the last statement, which in this case is the () which is returned by forM_.
The trick is to first create a list of all the line numbers you want to print, and to then loop through that list, printing each number in turn. So, like this:
import Control.Monad
import System.IO
main :: IO ()
main = do
hSetBuffering stdin LineBuffering
s <- getLine
let lineCount = read s :: Int
-- Create a list of the line numbers
lineNumbers = [1..lineCount]
-- `forM_` is like a "for-loop"; it takes each element in a list and performs
-- an action function that takes the element as a parameter
forM_ lineNumbers $ \ lineNumber -> do
line <- getLine
let number = read line :: Integer
result = number*2 --example
putStrLn $ "Line #" ++ show lineNumber ++ ": " ++ show result
return ()
Read the definition of forM_.
By the way, I wouldn't recommend using the old Haskell98 IO library. Use System.IO instead.
You could calculate the results, enumerate them, and then print them:
import IO
import Control.Monad (replicateM)
-- I'm assuming you start counting from zero
enumerate xs = zip [0..] xs
main :: IO ()
main = do
hSetBuffering stdin LineBuffering
s <- getLine
let number_of_lines_to_process = read s :: Integer
lines <- replicateM (fromIntegral(number_of_lines_to_process)) $ do
line <- getLine
let number = read line :: Integer
result = number*2 --example
return result
mapM_ putStrLn [ "Line "++show i++": "++show l | (i,l) <- enumerate lines ]
I'm still new at Haskell, so there could be problems with the program below (it does work). This program is a tail recursive implementation. The doLine helper function carries around the line number. The processing step is factored into process, which you can change according to the problem you are presented.
import System.IO
import Text.Printf
main = do
hSetBuffering stdin LineBuffering
s <- getLine
let number_of_lines_to_process = read s :: Integer
processLines number_of_lines_to_process
return ()
-- This reads "max" lines from stdin, processing each line and
-- printing the result.
processLines :: Integer -> IO ()
processLines max = doLine 0
where doLine i
| i == max = return ()
| otherwise =
do
line <- getLine
let result = process line
Text.Printf.printf "Line #%d: %d\n" (i + 1) result
doLine (i + 1)
-- Just an example. (This doubles the input.)
process :: [Char] -> Integer
process line = let number = read line :: Integer
in
number * 2
I'm a haskell rookie, so any critiques of the above are welcome.
Just as an alternative, I thought that you might enjoy an answer with minimal monad mucking and no do notation. We zip a lazy list of the user's data with an infinite list of the line number using the enumerate function to give us our desired output.
import System.IO
import Control.Monad (liftM)
--Here's the function that does what you really want with the data
example = (* 2)
--Enumerate takes a function, a line number, and a line of input and returns
--an ennumerated line number of the function performed on the data
enumerate :: (Show a, Show b, Read a) => (a->b) -> Integer -> String -> String
enumerate f i x = "Line #" ++
show i ++
": " ++
(show . f . read $ x) -- show . f . read handles our string conversion
-- Runover takes a list of lines and runs
-- an enumerated version of the sample over those lines.
-- The first line is the number of lines to process.
runOver :: [String] -> [String]
runOver (line:lines) = take (read line) $ --We only want to process the number of lines given in the first line
zipWith (enumerate example) [1..] lines -- run the enumerated example
-- over the list of numbers and the list of lines
-- In our main, we'll use liftM to lift our functions into the IO Monad
main = liftM (runOver . lines) getContents

Read n lines into a [String]

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

Resources