I'm getting what I think is an indent error with the following code
152 -- find the first one who can refute the scenario
153 let cs = map ($scenario) [ Suspect . getWho, Room . getWhere, Weapon . getHow ]
154 let (qs,rss) = break (not . null . intersect cs . hand) ps
155 unless (null rss) $ do
156 let refuter:ss= rss
157 let valid = intersect cs $ hand refuter
158
159 (refuter, shown) <- if cheated refuter
160 -- if the refuter is a cheater, just choose for him
161 then return (refuter, head valid)
162 else do
163 (refuter, shown) <- runStateT $ reveal scenario
164 -- make sure they don't cheat
165 return if shown `elem` valid
166 then (refuter, shown)
167 else (refuter { cheated = True }, head valid)
168 putTail (qs ++ refuter:ss)
169 return ()
The error I'm getting is
Game.hs:159:6:
The last statement in a 'do' construct must be an expression
When I delete or comment out lines 159-167, the error goes away.
What am I doing wrong?
You need to put parenthesis around the if-then-else in the value for return in line 165:
return (if shown `elem` valid
then (refuter, shown)
else (refuter { cheated = True }, head valid))
A pure if-then-else is not allowed by the Haskell grammar as a function argument, it has to be put in parenthesis to be used in that place. (It is a lexp while a function argument has to be an aexp.)
The error message generated is not very helpful in finding that issue.
return $ if ..
This should work. Matter of function application priority.
Related
module HW2sol
where import HW2types
ins :: Eq a => a -> Bag a -> Bag a
ins x [] = [(x,1)]
ins x (y:ys) =
if x == fst y
then (x, snd y + 1) : ys
else y : (ins x ys)
HMW2types in this code is just a file that contains all of the declarations for the bag type. I have even copied and pasted other functions from online and they get the same error. This function takes an element and adds it to a bag.
[2 of 2] Compiling HW2sol ( HMW2sol.hs, HMW2sol.o )
HMW2sol.hs:5:1: parse error on input `ins'
You may be aware of Haskell's indentation rules. Anywhere you have a block of declarations (as in a let <decls> in <expr>, or a where, etc) or a block of statements (as in a do block), or a block of patterns & branches (as in a case expression) Haskell identifies the start of each entry in the block by the following logic:
Identify the column of the first character of the first entry in the block. Call this column C.
The next line that is indented less than C indicates the end of the block (and is not part of the block).
Before the end of the block, any line that is indented exactly C characters starts a new entry in the block.
Before the end of the block, any line that is indented more than C is a continuation line of the previous entry
This logic is consistently applied to all of Haskell's "block" constructs. They all have to be aligned this way1. And it turns out that the top-level declarations in a module form an aligned block! We just don't usually bother to think of them that way because they are conventionally started at column 1 (which means it isn't possible to end the block as no line can start before the first column; people normally just put all their top-level declarations at the start of the line and indent any continuations without ever thinking about "aligning the module's main block").
However, your code does not (successfully) use this conventional layout. Because you didn't insert a linebreak after the where, the first declaration begins at column 7, not column 1!
where import HW2types
^
1234567
Your type declaration of ins begins on column 1, so by rule 2 above (1 is less than 7) this indicates the end of the module's block of definitions; the compiler has to parse ins :: Eq a => ... as something that can follow the main block in the module, instead of parsing it as a declaration in the main block. That's why you get a parse error (nothing can follow the main block).
If you start your module's main block at column 7 then all of your declarations have to be indented to column 7. This actually works:
module HW2sol
where import HW2types
ins :: Eq a => a -> Bag a -> Bag a
ins x [] = [(x,1)]
ins x (y:ys) =
if x == fst y
then (x, snd y + 1) : ys
else y : (ins x ys)
However you'll probably find it much easier to simply put a line break after the where and have import HW2types on a new line.
1 Alternatively, blocks and their entries can be explicitly delimited with braces and semicolons. But this is not usual style in Haskell.
How to understand the case args of in the following code?
main :: IO ()
main = do
args <- getArgs
case args of
[dir, mbytes] | [(bytes ,"")] <- reads mbytes
, bytes >= 1 -> findDuplicates dir bytes
(_) -> do
name <- getProgName
printf "Something went wrong - please use ./%s <dir> <bytes>\n" name
The guards in this case expression are making use of the PatternGuards extension, part of Haskell 2010 but not Haskell 98. The idea is that with this extension, your guards can do pattern-matching of their own, not just evaluate Bool expressions.
So your case expression has two patterns:
[dir, mbytes]
and the wildcard pattern. If [dir, mbytes] does match with args, the pattern match still might not succeed: its guards need to apply. It has two guards:
[(bytes ,"")] <- reads mbytes
which means that calling reads mbytes must match with [(bytes, "")], and
bytes >= 1
which is an ordinary boolean expression.
If all of those pattern matches and guards succeed, then the first clause of the case is the one that is used; otherwise, we fall through to the default clause and print an error message.
I am getting this compile error:
Files.hs:47:17: parse error on input ‘->’
Failed, modules loaded: none.
In the following section of code:
main :: IO ()
main = do
args <- getArgs
let f = case args of
("W":_) -> eoltoW
-- ^ here's 47:17
("U":_) -> eoltoU
_ -> fail "2 - 3 arguments required"
case args of
[_,i,o] -> editWith f i o
[_,i] -> catWith f i
[_] -> fail "2 - 3 arguments required"
While I understand the logic could use some tidying up, I do not see where I am going wrong with case syntax. I figure it might be some weird interaction with do and let, but I can't find any clue as to how to correct it.
Note, I have ensured that I only use spaces for indentation
Edit:
It seems that adding a single space further of indentation (as below) is sufficient to prevent the error, but I am unclear as to why.
main = do
args <- getArgs
let f = case args of
("W":_) -> eoltoW
-- ^ here's 47:17
("U":_) -> eoltoU
_ -> fail "2 - 3 arguments required"
This is described in 2.7 and 10.3. Basically, the rule for let … in a do block* is that all bindings have to be indented the same way:
let a = …
b = …
c = …
Furthermore, the "…" have to be more indented than the layout list. For example, the following is a syntax error:
let a =
10
in a
In order to create a new layout-list, we need to indent it further (see note 1 in section 10.3), which is why
let a =
10
in a
is completely fine. The same holds for your case. All of the cases have to be further indented than f due to the off-side rule.
* that rule actually holds** for more, i.e. for let, where, do and of.
** well, as long as you don't introduce additional braces
I'm solving the 8-queens problem in Haskell using only basic functions nothing fancy
this is the code:
queens = [[x1,x2,x3,x4,x5,x6,x7,x8]|x1<-[1..8],x2<-[1..8],x3<-[1..8],x4<-[1..8],x5<-[1..8],x6<-[1..8],x7<-[1..8],x8<-[1..8],safeH [x2,x3,x4,x5,x6,x7,x8] x1,safeD [x2,x3,x4,x5,x6,x7,x8] x1 [x1,x2,x3,x4,x5,x6,x7,x8] 1]
safeH l e = if elem e l then False
else if length (l)/=0 then safeH(tail l)(head l)
else True
safeD l e xs n = if last(xs)/=e || length xs == 0 then
if length(l)/=0 then
if (head(l)+n==e || head(l)-n==e) then False
else safeD(tail l)(e)(xs)(n+1)
else safeD(tail xs)(head xs)(tail xs)(1)
else True
To clarify the SafeH function checks that no queens are in the same row H stands for Horizantly while the SafeD is supposed to check for diagonal conflicts
I am sure that the SafeH function is okay the problem with SafeD
and when compiling the code it gives me no problems but when calling the queens function
it gives me this error:
[1 of 1] Compiling Main ( y.hs, interpreted )
Ok, modules loaded: Main.
*Main> queens
*** Exception: Prelude.last: empty list
can anyone please help me?? thanks in advance for every thing :)
You can fix the immediate problem by checking the length of xs before calling last:
safeD l e xs n = if length xs == 0 || last(xs)/=e then ...
However, you will then run into another problem because you call safeD(tail xs)(head xs)(tail xs)(1) inside the then part of this branch, and you can reach the then part of this branch when length xs == 0.
I strongly recommend learning a little bit about pattern matching (Gentle Intro section, Haskell Report section) and trying to write this entire code snippet without ever calling head, tail, init, last, or length. Instead, use the two patterns [] for matching empty lists and (x:xs) (or similar) for matching lists that start as x and end with xs; if necessary, a call to reverse once in a while would be okay.
Good luck, and let us know how you fare and where you get stuck!
Ever thought of solving this problem for zero queens first?
Then for one queen?
Then spot the inductive / recursive pattern?.. I am not quoting the 3-liner solution, as it looks like your homework.
>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!