>main :: IO ()
main = withPostgresqlConn "host=localhost user=Rocko port=5432 dbname=Rocko" $ runSqlConn $ do
runMigration migrateAll
let compDay = C.fromGregorian 2011 11 21
match <- selectList
[TestStartDate ==. compDay,
TestEstimatedEnd ==. compDay,
TestStatus /<-. [Passed,Failed]] []
scheduled <- selectList [TestStatus ==. Scheduled] []
-- liftIO $ print scheduled
liftIO $ print match
if (L.null match == True) then (liftIO $ print "date available!!!! ") else (liftIO $ print "date not available")
return ()
I'm trying to determine if a particular Day meets this criteria: is not equal to a TestStartDate, is not equal to a TestEstimatedEnd, and neither Passed not Failed is a member of TestStatus.
However, I want to demonstrate that with the date I picked (which should have a match on an TestEstimatedEnd) fails to do the right thing. It should say , :date not available. So what is wrong with my logic?
> id | firmware | version | startDate | estimatedEnd | status
>----+---------------------------+------------+------------+--------------+-----------
>1 | BCC Admin | 0.0.00.001 | 2011-11-19 | 2011-11-21 | Scheduled
>ghcifoo> main
"date available!!!! "
This is a difficult problem to replicate so what I'm writing is a pretty wild guess, but here goes:
Lets work backwards from the final result
if (L.null match == True) then (liftIO $ print "date available!!!! ") else (liftIO $ print "date not available")
This line clearly evaluated the then condition. Ergo (L.null match == True) was True. My first question is why the == True clause? L.null match should work just as well by itself.
Now we know that L.null match must have been True, but the line above would seem to indicate that match contains one record. So at this point I would suspect that L.null is perhaps not the function you think it is or match doesn't contain what the output is leading us to believe it does. My next debugging suggestion would be to test match against some other properties (is there a length function maybe?) and see if the problem is with L.null or match. Another thought is to move the print statement after the if. That should not change anything (certainly not in Haskell!), but the response from a database query is occasionally weird. (e.g. not a list but a stream of results that gets consumed as they are used.)
Good Luck!
Related
I wrote a function in Haskell to return a list. I want to get the return value of the function and store in another variable for future use. The code I have written is given below
module Main
where
import System.IO
main =do
let list=doCal
doCal =do
hSetBuffering stdin LineBuffering
putStrLn "Give me a number (or 0 to stop):"
num <- getLine
let number = read num
if number==0
then
return []
else do
rest <-doCal
return (number:rest)
When I try to run this, I got an error
Cal.hs:7:9: error:
The last statement in a 'do' block must be an expression
let list = doCal
|
7 | let list=doCal
| ^^^^^^^^^^^^^^
Failed, no modules loaded.
How to store the return value of a function to a variable in Haskell?
The same way you already did it with rest in doCal.
main = do
list <- doCal
But you also need to have main do something and return a value. So you might write
main = do
list <- doCal
print list
This will work because print list returns (), which is a value in Haskell (its just the only value of its type).
I am writing a program in Haskell which repeatedly takes its most recent result and uses this to compute the next result. I want to be able to see the newest result in response to user input, so I tried something like this:
main = mainhelper 0
mainhelper count = do
count <- return (count + 1)
line <- getLine
if null line
then do mainhelper count
else do
putStrLn $ show count
return ()
I was hoping that getLine would return an empty line if the user hasn't entered anything, but this doesn't happen, instead the program does nothing until it receives user input. Is there a way around this?
One simple solution is to fork a thread for the complicated computation and communicate with the main UI thread via MVar. For example:
import Control.Exception
import Control.Monad
import Control.Concurrent
thinkReallyHard x = do
threadDelay 1000000 -- as a proxy for something that's actually difficult
evaluate (x+1)
main = do
v <- newMVar 0
forkIO (forever (modifyMVar_ v thinkReallyHard))
forever (getLine >> readMVar v >>= print)
You may wonder about the role of evaluate in thinkReallyHard. The subtlety there is that MVars are lazy -- they can contain thunks just as easily as computed values. In particular, this means it's easy to accidentally push all the pure computation from the forked thread into the thread that's reading and using the contents of the MVar. The call to evaluate simply forces the forked thread to finish the pure computation before writing to the MVar.
It does return an empty line if you hit enter without entering text -- you just immediately prompt for more input, so it might look like nothing is happening. But if you run the program, hit enter three times, then enter something non-empty, you'll see that the final count reflects the multiple entries.
Here's a modified version of your code that does the same thing, but is slightly more canonical:
main = mainhelper 0
mainhelper count = do
let count' = count + 1
line <- getLine
if null line
then mainhelper count'
else print count'
Rather than count <- return (count + 1), you can write let count' = count + 1 -- this is a pure binding, not something that needs to invoke the IO monad (as you're doing with <- and return). But I used count' instead of count because otherwise that will create a recursive binding. The '-suffixing is a standard idiom for a "modified version" of an identifier.
Next I switched putStrLn . show to print, which is part of the Prelude and does exactly that.
I got rid of the return () because print (and putStrLn) already have the type IO (). This allows you to elide the do statements, as there's now a single IO expression in each branch of the if.
It's not really clear what you're trying to do here that's different from what you are doing -- the code does (in imperative terms) increment a counter every time the user presses enter, and displays the state of the counter every time the user enters some non-empty text.
Here's another version that prints the counter every time, but only increments it when prompted, which may or may not be helpful to you:
main = mainhelper 0
mainhelper count = do
print count
line <- getLine
mainhelper (if null line then count else succ count)
I'm using succ, the successor function, instead of the explicit + 1, which is just a style preference.
I'm currently working my way through Learn You a Haskell for Great Good, and I'm trying to modify one of the code snippets in chapter nine, "Input and Output" to handle errors correctly:
main = do
(command:args) <- getArgs
let result = lookup command dispatch
if result == Nothing
then
errorExit
else
let (Just action) = result
action args
where
dispatch :: [(String, [String] -> IO ())]
is an association list
and
errorExit :: IO ()
is some function that prints an error message.
Compiling this with GHC gives the error message
todo.hs:20:13: parse error in let binding: missing required 'in'
which (to my understanding), seems to be saying that the "let" here doesn't realise it's in a "do" block.
Adding "do" on lines five and seven (after "then" and "else" respectively), changes the error message to
todo.hs:20:13:
The last statement in a 'do' block must be an expression
let (Just action) = result
todo.hs:21:5: Not in scope: `action'.
and now, whilst I agree with the first error message, I also have that one of my variables has jumped out of scope? I've double checked my alignment, and nothing seems to be out of place.
What is the appropriate way to assign a varaible within an if clause that is within a do block?
My suggestion is to not use if in the first place, use case. By using case you get to test the value and bind the result to a variable all in one go. Like this:
main = do
(command:args) <- getArgs
case lookup command dispatch of
Nothing -> errorExit
Just action -> action args
For a more in-depth discussion on why we should prefer case over if see boolean blindness.
#svenningsson suggested the right fix. The reason your original fails is because let clauses can only appear at the top level of a do block - they're simple syntactic sugar that doesn't look into inner expressions:
do let x = 1
y
desugars to the let expression
let x = 1 in y
Alas, in a do block, an expression clause like if ... then ... else ... has no way to declare variables in the rest of the do block at all.
There are at least two possible ways to get around this.
Absorb the remainder of the do block into the expression:
main = do
(command:args) <- getArgs
let result = lookup command dispatch
if result == Nothing
then
errorExit
else do
let (Just action) = result
action args
(This is essentially the method #svenningsson uses in his better case version too.)
This can however get a bit awkward if the remainder of the do expression needs to be duplicated into more than one branch.
("Secret" trick: GHC (unlike standard Haskell) doesn't actually require a final, inner do block to be indented more than the outer one, which can help if the amount of indentation starts getting annoying.)
Pull the variable declaration outside the expression:
main = do
(command:args) <- getArgs
let result = lookup command dispatch
action <- if result == Nothing
then
errorExit
else do
let (Just action') = result
return action'
action args
Here that requires making up a new variable name, since the pattern in the let clause isn't just a simple variable.
Finally, action was always out of scope in the last line of your code, but GHC works in several stages, and if it aborts in the parsing stage, it won't check for scope errors. (For some reason it does the The last statement in a 'do' block must be an expression check at a later stage than parsing.)
Addendum: After I understood what #Sibi meant, I see that result == Nothing isn't going to work, so you cannot use if ... then ... else ... with that even with the above workarounds.
You are getting an error because you are trying to compare values of function type. When you perform the check if result == Nothing, it tries to check the equality of Nothing with the value of result which is a type of Maybe ([String] -> IO ()).
So, if you want it to properly typecheck, you have to define Eq instances for -> and that wouldn't make any sense as you are trying to compare two functions for equality.
You can also use fmap to write your code:
main = do
(command:args) <- getArgs
let result = lookup command dispatch
print $ fmap (const args) result
I'm trying to write a function in Haskell which checks for some things and then recurses based on some minimal user input. In order to do that I think I have to use do blocks.
cip :: [Argument] -> [Argument] -> Bool -> Bool -> IO()
cip (a:args) pargs burden gameover = do
let nasko = a:pargs
putStrLn (getPremise a)
let newgraph = Carneades.mkArgGraph nasko
let newcaes = (CAES (newgraph,audience2,assStandarts))
let answer = (acceptable (mkProp (getPremise a)) newcaes )
print answer
if(answer==True)
then (cip args nasko burden gameover)
else do
print "One of the arguments is not proved. Here are the premises that need proving"
print (propsForFixing newcaes a)
print "Let's see what you have for the first Propositon"
--add an if to check if no applicable arguments.
print (argumentScanHelp (head (propsForFixing newcaes a)) args)
print "\n Would you like me to apply the firt one? Y/N"
choice <- getLine
if(choice=="Y") then do print "applying the argument"
let applicabee = head (argumentScanHelp (head (propsForFixing newcaes a)) args)
print "Argument targeted"
let newargs = delete applicabee args
let newpargs = applicabee:nasko
print "Argument applied sucsessfuly. Recusing again"
(cip newargs newpargs burden gameover)
return()
It hurts my eyes just by looking at it, but that's do blocks for you.
Everything up to the third do block is okay. But then on this line:
if(choice=="Y") then do print "applying the argument"
let applicabee = head (argumentScanHelp (head (propsForFixing newcaes a)) args)
The complier starts crying:
Main.hs:209:73: parse error on input `let'
Tried a all kinds of different indentations but I can't seem to get it to work.
I don't want to use separate functions, because that means I'll have to pass a lot of arguments around constantly.
Can anyone help me get it right? Also an explanation of what exactly the specifications for nested do block are would be greatly appreciated.
The cause of the error I believe is the misuse of the if expression. You use it as if it were an if statement that exists in most imperative languages. Simply put there must always be an else.
However, in do blocks it makes sense to "not have an else", something like an if statement without an else. Luckily the Control.Monad module will provide you with a function for exactly that:
import Control.Monad (when)
(...)
when (choice=="Y") $ do print "applying the argument"
let applicabee = ...
You seem to already use nested do blocks in the correct way which is good, which basically is that you must indent properly.
PS. Also make sure your last return () is indented like the rest of your code! DS.
It would seem that Hamlet's $case expression should be remarkably useful, but I can't figure out how one would match against an record type with multiple constructors short of pattern matching (with a unique name) each of the fields. Say I have a data type,
data A = A1 { v1,v2,v3 :: Int }
| A2 { g :: Double}
In my template, I would want to render A1 values differently from A2 values. One would think I could simply do,
$case myA
$of a#(A1 {})
<p>This is an A1: #{show $ v1 a}
$of a#(A2 {})
<p>This is an A2: #{show $ g a}
Unfortunately, this snippet fails to compile with a syntax error, suggesting that the # syntax isn't supported. If I remove the a#, I get another syntax error, this time suggesting that the record brace notation also isn't supported.
Finally, in desperation, once can try,
$case myA
$of A1 _ _ _
...
But alas, even this doesn't compile (conflicting definitions of _). Consequently, it seems that the only option is,
$case myA
$of A1 v1 v2 v3
...
This sort of order-based pattern matching gets extremely tiresome with large datatypes, especially when one is forced to name every field.
So, what am I missing here? Is case analysis in Hamlet really as limited as it seems? What is the recommended way to match against the constructors of a ADT (and later refer to fields)? Is the fact that I even want to do this sort of matching a sign that I'm Doing It Wrong(TM)?
You can track hamlet processing.
The answer is in the non-exposed module Text.Hamlet.Parse where
controlOf = do
_ <- try $ string "$of"
pat <- many1 $ try $ spaces >> ident
_ <- spaceTabs
eol
return $ LineOf pat
where
ident = Ident <$> many1 (alphaNum <|> char '_' <|> char '\'')
so only a sequence of one or more (spaces followed by (identifier or wildcard)) is accepted.
You may extend it from here.
Cheers!