I am writing in Haskell and want to print a statement in a function and also call another function and I dont know why this isn't working. Could someone possibly tell me what I'm doing wrong or provide a more logical solution?
My error is:
Couldn't match expected type `[a0]' with actual type `IO ()'
In the return type of a call of `putStrLn'
In a stmt of a 'do' block: putStrLn "Missing closing bracket"
In the expression:
do { putStrLn "Missing closing bracket";
evaluate_input }
The code:
bracket_content [] 0 = []
bracket_content (first:rest) counter
| is_open_bracket first = first : bracket_content rest (counter + 1)
| is_close_bracket first = first : bracket_content rest (counter - 1)
| counter == 0 = []
| otherwise = first : bracket_content rest counter
bracket_content _ _ = do putStrLn "Missing closing bracket" --error here
evaluate_input
evaluate_input :: IO ()
evaluate_input = do
putStrLn "Enter Expression or 'q' to exit calculator: "
expression <- getLine
case expression of
a:as -> return a
unless (expression == ['q']) $ evaluate_expression expression
where evaluate_expression e = do
putStrLn . show $ calculate e
evaluate_input
Your problem is that you are trying to make bracket_content return two different types. The first two patterns return lists, while the last pattern returns an IO (). The compile error is indicating that GHC inferred (because you use cons (:) on the recursive call) or read from your type signature the type of bracket_content to be
bracket_content :: [a] -> Int -> [a]
but your last pattern returns an IO (). I think you might be trying to return a list of characters that you can later print: you are appending an open bracket to whatever the recursive call returns.
One potential solution is to make every pattern return an IO ():
bracket_content _ 0 = return ()
bracket_content (first:rest) counter
| is_open_bracket first = do putChar first
bracket_content rest (counter + 1)
| is_close_bracket first = do putChar first
bracket_content rest (counter - 1)
| otherwise = do putChar first
bracket_content rest counter
bracket_content _ _ = do putStrLn "Missing closing bracket"
evaluate_input
I'm not sure if this will accomplish what you want, but at least it compiles. The difference between your version and my version is that in my version, every pattern returns an IO (), giving your function the signature:
bracket_content :: [Char] -> Int -> IO ()
Also notice that I removed your guard
| counter == 0 = []
because I added it to the first pattern, which now prints nothing if the counter is 0, regardless of if the list is empty or not.
Related
I'm a newbie in Haskell. Was trying a code to take input string in user defined function and further perform tasks as per argument passed to function in main.
main :: IO()
main=do
{
print(f 2)
}
f::Int->Int
f n=do
{
inp<-getLine;
if (inp=="hello") then (n+2);
else (n);
}
Since this function takes int and returns int, I defined it as Int->Int. However I feel something's missing.
I'm getting the following error:-
[1 of 1] Compiling Main ( main.hs, main.o )
main.hs:9:5: error:
• Couldn't match expected type ‘Int’ with actual type ‘IO b0’
• In a stmt of a 'do' block: inp <- getLine
In the expression:
do inp <- getLine
if (inp == "hello") then (n + 2) else (n)
In an equation for ‘f’:
f n
= do inp <- getLine
if (inp == "hello") then (n + 2) else (n)
|
9 | inp<-getLine;
| ^^^^^^^^^^^^
main.hs:10:29: error:
• Couldn't match expected type ‘IO b0’ with actual type ‘Int’
• In the expression: (n + 2)
In a stmt of a 'do' block:
if (inp == "hello") then (n + 2) else (n)
In the expression:
do inp <- getLine
if (inp == "hello") then (n + 2) else (n)
|
10 | if (inp=="hello") then (n+2);
| ^^^
main.hs:11:29: error:
• Couldn't match expected type ‘IO b0’ with actual type ‘Int’
• In the expression: (n)
In a stmt of a 'do' block:
if (inp == "hello") then (n + 2) else (n)
In the expression:
do inp <- getLine
if (inp == "hello") then (n + 2) else (n)
|
11 | else (n);
| ^
How to rectify this error??
A do block almost always indicates that you are defining a monadic computation(1). Therefore the type of f has to be Int -> IO Int (IO is induced by the use of getLine here). Additionally, since the result has to be contained in a monadic context, you should wrap n+2 and n with return.
So the final code of f should be
f :: Int -> IO Int
f n = do
inp <- getLine
if inp == "hello" then return (n + 2)
else return n
Note that the use of f in main has to be adjusted accordingly.
(1)sometimes applicative, but anyway
I have the following code:
import Debug.Trace (trace)
mtrace :: Show a => String -> a -> a
mtrace msg value =
trace (msg ++ show value) value
isVowel :: Char -> Bool
isVowel = (`elem` "AEIOU")
vowelSlice :: String -> ([Maybe Char], String)
vowelSlice "" = ([], [])
vowelSlice (c:s)
| isVowel c = (Nothing:chars, c:vowels)
| otherwise = (Just c:chars, vowels)
where (chars, vowels) = vowelSlice s
stringTogether :: [Maybe Char] -> String -> String
stringTogether [] "" = ""
stringTogehter (Just c:cs) vowels = c:stringTogether cs vowels
stringTogehter (Nothing:cs) (v:vs) = v:stringTogether cs vs
process :: String -> String
process s = stringTogether (mtrace "chars: " chars) (mtrace "vowels: " cycledVowels)
where
(chars, vowels) = vowelSlice s
cycledVowels = tail vowels ++ [head vowels]
main :: IO ()
main = do
line <- getLine
putStrLn $ process line
for testing I run my file using the runhaskell command and the I enter HELLO PEOPLE as user input once the program is running. I'm expecting the output: HELLE POEPLO or something similar since my program is meant to shift the vowels only. My program works fine until it tries to run the stringTogether method. Specifically the issue lies with the pattern matching, I have an array:
[Just 'H',Nothing,Just 'L',Just 'L',Nothing,Just ' ',Just 'P',Nothing,Nothing,Just 'P',Just 'L',Nothing]
and a pattern
(Just c:cs) vowels that I expect it to match but somehow it doesn't seem to work. When I run the code and enter HELLO WORLD I receive the following error:
18:1-25: Non-exhaustive patterns in function stringTogether I logged a few things using the trace module and everything looks as expected before entering the stringTogether function
I'm probably overlooking something really obvious but I just can't get my head around why the pattern match won't work, I hope someone is able to help. Thanks in advance!
The pattern match fails because of a typo, 2 separate functions were defined instead of the intended one: stringTogether and stringTogehter. The patterns were valid but the compiler failed to find them because they had mismatching names. The function technically stringTogether only had one pattern [] "" so when the list was passed it raised the 18:1-25: Non-exhaustive patterns in function stringTogether error.
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.
I don't understand this type error:
Couldn't match expected type `[t0]' with actual type `IO ()'
In the return type of a call of `printv'
In a stmt of a 'do' expression: px <- printv x
In the expression:
do { px <- printv x;
sep <- print ", ";
rest <- prints xs;
return (px : sep : rest) }
From:
data Value = IntValue Int
| TruthValue Bool
deriving (Eq, Show)
printv :: Value -> IO()
printv (IntValue i) = print i
printv (TruthValue b) = print ("boolean" ++ show b)
prints :: [Value] -> [IO()]
prints [] = []
prints (x:xs) = do px <- printv x
sep <- print ", "
rest <- prints xs
return (px:sep:rest)
It looks to me like every element (px) is converted into an IO() action, and then that is added to a list of the same things, thus producing an [IO()] list.
What am I missing here? Converting it to a list of strings, by removing the print's, works fine.
You're missing the return on the [] case of prints:
prints [] = return []
However, your prints is very strange. It returns a [()], because print is outputting strings to the console, not returning them.
Do you mean to return strings from your printv function?
Since you're trying to pretty print a syntax tree, here's roughly the right way to do it:
Use pretty-printing combinators
Use a pretty typeclass
Like so:
import Text.PrettyPrint
import Data.List
data Value
= VInt Int
| VBool Bool
deriving (Eq, Show)
class Pretty a where
pretty :: a -> Doc
instance Pretty Value where
pretty (VInt i) = int i
pretty (VBool b) = text "Boolean" <+> text (show b)
draw :: [Value] -> String
draw = intercalate ", " . map (render.pretty)
main = putStrLn $ draw [VInt 7, VBool True, VInt 42]
Running it:
*A> main
7, Boolean True, 42
Take a closer look at the type of your function:
prints :: [Value] -> [IO()]
But if we now take a look at prints [] = [], this can't match, because the type of that one is
prints :: [t] -> [a]
Therefore, you missed using prints [] = return [], to make it work.
If you're not evaluating an IO action, you don't need a do block. Just treat IO () as a normal type.
prints (x:xs) = printv x : print ", " : prints xs
You don't want prints to return an array of IO actions. You want it to return a single IO action that represents each of the IO actions bound together. Something like:
prints xs = mapM_ (\x -> printv x >> putStr ", ") xs
Except that I don't think the new lines are going to end up where you want them.
Look at the documentation for mapM and sequence for more information. In particular, the implementation of sequence is probably similar to what you're trying to do.
However, I would really recommend that instead doing all the work in an IO function, you should write a pure function to render the textual format you want, and then just print that. In particular, it seems that an instance of Show for Value would be appropriate.
instance Show Value where
show (IntValue i) = show i
show (TruthValue b) = "boolean " ++ show b
That way you can just call print value rather than printv value, and if you really wanted to you could define prints as follows.
import Data.List
prints :: (Show a) => [a] -> IO ()
prints = putStrLn . intercalate ", " . map show`.
Im new to Haskell!!
I wrote this code:
import Data.List
inputIndex :: [String] -> [String] -> Bool
inputIndex listx input = and [x `elem` listx |x <- input]
inputIndex = if inputIndex == true
then putStrLn ("ok")
It works fine without the if statement but when I put the if statement the following error is shown:
Syntax error in expression (unexpected `}', possibly due to bad layout)
What am I doing wrong here?
Thanks
A couple of things are wrong here:
You will need an else clause.
True must be capitalized.
inputIndex must always take two arguments (right now it does not, in the last case).
I guess you want something like this...
inputIndex :: [String] -> [String] -> IO ()
inputIndex listx input = if inputIndex' listx input
then putStrLn ("ok")
else putStrLn ("not ok")
where
inputIndex' :: [String] -> [String] -> Bool
inputIndex' listx input = and [x `elem` listx |x <- input]
(Here I defined a new function with a near-identical name, by appending a prime/apostrophe. By defining it in the where clause, it is only visible to the outer inputIndex function. You can call this a helper-function, if you will. I could also have chosen a completely different name, but I'm uncreative.)
You could also condense this to the following (which is also more general):
allPresent :: (Eq t) => [t] -> [t] -> IO ()
allPresent xs ys = putStrLn (if and [y `elem` xs | y <- ys] then "ok" else "not ok")
It's "True", not "true".
Your second inputIndex implementation is not compatible with the first one. All your pattern cases for a function must have the same signature ([String] -> [String] -> Bool)
The error you show here is not generated by this code, because there is no '}' here.
putStrLn has signature String -> IO() while your inputIndex looks like it's supposed to be pure - just return the value and print it somewhere else.