Haskell: Expected Laziness, Why is this Evaluated? - haskell
I have a function sideH which runs the risk of Prelude.head []. Hence, I have written it using Maybe, to avoid this:
sideH :: Residue -> Maybe (Atom, Atom)
sideH res
-- Make sure the elements exist
| nits /= [] && cars /= [] && oxys /= [] = Just (newH1, newH2)
| otherwise = Nothing where
...
The above works exactly as expected, without error. Now, in the function which calls sideH (which is not a do construct), I must handle the situation that sideH returns Nothing:
callerFunc :: [Residue] -> Aromatic -> [(Double, Double)]
callerFunc [] _ = []
callerFunc (r:rs) aro
-- Evaluate only if there is something to evaluate
| newHs /= Nothing = (newH1Pos, newH2Pos)
| otherwise = callerFunc rs aro where
newHs = sideH r
newH1Pos = atomPos $ fst $ fromJust newHs
newH2Pos = atomPos $ snd $ fromJust newHs
If I try to evaluate newH1Pos or newH2Pos when newH = Nothing, it will fail because fromJust Nothing is an error. However, I expect this to never happen. I expect the callerFunc to evaluate newHs, which is either Just something or Nothing. If it is Nothing, then the callerFunc will go to its next step without ever evaluating newH1Pos or newH2Pos. This does not appear to be the case. I get an *** Exception: Maybe.fromJust: Nothing error exactly where I would expect newHs to return Nothing.
I was asked for more code. I am trying to come up with a minimum situation that reproduces the error, but in the mean time, here is the complete problematic callerFunc code.
-- Given a list of residues and an aromatic, find instances where there
-- is a Hydrogen bond between the aromatic and the Hydrogens on Gln or Asn
callerFunc :: [Residue] -> Aromatic -> [(Double, Double)]
callerFunc [] _ = []
callerFunc (r:rs) aro
-- GLN or ASN case
| fst delR <= 7.0 && (resName r == gln || resName r == asn) &&
newHs /= Nothing && snd delR <= 6.0 =
[(snd delR, fst delR)] ++ hBondSFinder rs aro
| otherwise = hBondSFinder rs aro where
-- Sidechain identifying strings
gln = B.pack [71, 76, 78]
asn = B.pack [65, 83, 78]
-- Get the location of the Hydrogens on the residue's sidechain
newHs = sideH r
newH1Pos = atomPos $ fst $ fromJust newHs
newH2Pos = atomPos $ snd $ fromJust newHs
-- Get the location of the Nitrogen on the mainchain of the Residue
ats = resAtoms r
backboneNPos = atomPos $ head $ getAtomName ats "N"
hNVect1 = Line2P {lp1 = newH1Pos, lp2 = backboneNPos}
hNVect2 = Line2P {lp1 = newH2Pos, lp2 = backboneNPos}
interPoint1 = linePlaneInter (aroPlane aro) hNVect1
interPoint2 = linePlaneInter (aroPlane aro) hNVect2
delR = minimum [(interPoint1 `dist` newH1Pos, delr1),
(interPoint2 `dist` newH2Pos, delr2)]
delr1 = interPoint1 `dist` (aroCenter aro)
delr2 = interPoint2 `dist` (aroCenter aro)
I know this is a painful code dump. I am trying to whittle it down.
The answer to this question (asked in the comments) doesn't fit in a comment: "I am not sure how I would use pattern matching, here, to remove these if statement.".
Like this, for example, though there are still some code smells left that could likely be improved with some additional refactoring:
sideH :: Residue -> Maybe (Atom, Atom)
sideH res = case (nits, cars, oxys) of
(_:_, _:_, _:_) -> Just (newH1, newH2)
_ -> Nothing
where
...
If you have flexible morals, you might try something like this:
sideH :: Residue -> Maybe (Atom, Atom)
sideH res = do
_:_ <- return nits
_:_ <- return cars
_:_ <- return oxys
return (newH1, newH2)
where
...
Again, both of these code samples can likely be improved about tenfold if there's a bit more context and code available to make recommendations for.
Related
When can I rely on Haskell to read a list lazily?
Why do I get an infinite loop (<<loop>>) runtime error here? file feedback.hs: plus1 :: [Int]->[Int] -- add 1 to input stream plus1 [] = [] plus1 (x:xs) = (x+1): plus1 xs to10 :: [Int] -> [Int] -- stop the input stream when it gets to 10 to10 (x:xs) | x < 10 = x : to10 xs | otherwise = [] to10plus :: [Int] -> ([Int], Int) -- like to10 but also return the count to10plus (x:xs) | x < 10 = (x, 1) `merge` (to10plus xs) | otherwise = ([], 0) where merge (a, b) (as, bs) = (a:as, b+bs) main = do let out = plus1 $ 1: to10 out putStrLn $ show out -- gives [2,3,4,5,6,7,8,9,10] let out = plus1 $ 1: out2 out2 = to10 out putStrLn $ show out -- same as above let out = plus1 $ 1: out2 (out2, count) = to10plus out putStrLn $ show (out, count) -- expect ([2,3,4,5,6,7,8,9,10], 8) -- but get runtime error: <<loop>> $ ghc feedback.hs [1 of 1] Compiling Main ( feedback.hs, feedback.o ) Linking feedback ... $ ./feedback [2,3,4,5,6,7,8,9,10] [2,3,4,5,6,7,8,9,10] feedback: <<loop>>
You can fix to10plus by using an irrefutable match (i.e., a ~ prefix) in your definition of merge: merge (a, b) ~(as, bs) = (a:as, b+bs) The reason for the difference in behavior between to10 and to10plus is that to10 can return the first element of the list without having to evaluate to10 xs and so without inspecting xs. In contrast, before it can return anything, to10plus must successfully call merge with the arguments (x, 1) and to10plus xs. For this call to succeed, to10plus xs must be evaluated far enough to ensure it matches the pattern (as, bs) used in the definition of merge, but that evaluation requires inspecting elements of xs, which aren't available yet. You could also have avoided the problem by defining to10plus a little differently: to10plus (x:xs) | x < 10 = (x:as,1+bs) | otherwise = ([], 0) where (as,bs) = to10plus xs Here, to10plus can provide the first element x of the first part of the tuple without trying to evaluate as, and so without trying to pattern match to10plus xs with (as,bs) in the where clause. A let clause would have done the same thing: to10plus (x:xs) | x < 10 = let (as,bs) = to10plus xs in (x:as,1+bs) | otherwise = ([], 0) As #luqui points out, this is a difference in the timing for pattern matches made by let and where statements: let (a,b) = expr in body -- OR -- body where (a,b) = expr versus case statements / function definitions: case expr of (a,b) -> body -- OR -- f (a,b) = body -- AND THEN EVALUATING: -- f expr The let and where statements match patterns lazily, meaning that expr isn't matched to the pattern (a,b) until a or b are evaluated in the body. In contrast, for the case statement, expr is matched to (a,b) right away, before the body is even examined. And given the above definition for f, the argument to f will be matched to (a,b) as soon as the expression f expr is evaluated without waiting until a or b is needed in the function body. Here are some working examples to illustrate: ex1 = let (a,b) = undefined in print "okay" ex2 = print "also okay" where (a,b) = undefined ex3 = case undefined of (a,b) -> print "not okay" ex4 = f undefined f (a,b) = print "also not okay" main = do ex1 -- works ex2 -- works ex3 -- fails ex4 -- fails Adding ~ changes the behavior for case / function definitions so the matching takes place only when a or b are needed: ex5 = case undefined of ~(a,b) -> print "works fine" ex6 = g undefined g ~(a,b) = print "also works fine" ex7 = case undefined of ~(a,b) -> print $ "But trying " ++ show (a+b) ++ " would fail"
Exception: Prelude.head: empty list in Haskell
I can't figure out why I'm getting this error. I have already read all the questions already asked about this error and I don't have any of those issues. Can someone please help. The comments are the hard code for the given example so we can use a top-down approach. When I get done with a function I comment out the hard code. I have only implemented the first 2 functions. In ghci when you run the file, type 'main', if it prints true the code is working. When I test both functions separately they return true but together they return the above error. import Data.List ((\\), sort) type Board = [[Int]] inputBoard :: Board inputBoard = [[5,3,0, 0,7,0, 0,0,0], [6,0,0, 1,9,5, 0,0,0], [0,9,8, 0,0,0, 0,6,0], [8,0,0, 0,6,0, 0,0,3], [4,0,0, 8,0,3, 0,0,1], [7,0,0, 0,2,0, 0,0,6], [0,6,0, 0,0,0, 2,8,0], [0,0,0, 4,1,9, 0,0,5], [0,0,0, 0,8,0, 0,7,9]] solvedBoard :: Board solvedBoard = [[5,3,4, 6,7,8, 9,1,2], [6,7,2, 1,9,5, 3,4,8], [1,9,8, 3,4,2, 5,6,7], [8,5,9, 7,6,1, 4,2,3], [4,2,6, 8,5,3, 7,9,1], [7,1,3, 9,2,4, 8,5,6], [9,6,1, 5,3,7, 2,8,4], [2,8,7, 4,1,9, 6,3,5], [3,4,5, 2,8,6, 1,7,9]] type Coords = (Int,Int) type BoardElement = (Coords,Int) inputBoardElements :: [BoardElement] inputBoardElements = [((0,0),5),((0,1),3),((0,4),7),((1,0),6),((1,3),1),((1,4),9),((1,5),5), ((2,1),9),((2,2),8),((2,7),6),((3,0),8),((3,4),6),((3,8),3),((4,0),4), ((4,3),8),((4,5),3),((4,8),1),((5,0),7),((5,4),2),((5,8),6),((6,1),6), ((6,6),2),((6,7),8),((7,3),4),((7,4),1),((7,5),9),((7,8),5),((8,4),8), ((8,7),7),((8,8),9)] inputBoardEmpty :: [Coords] inputBoardEmpty = [(0,2),(0,3),(0,5),(0,6),(0,7),(0,8),(1,1),(1,2),(1,6),(1,7),(1,8), (2,0),(2,3),(2,4),(2,5),(2,6),(2,8),(3,1),(3,2),(3,3),(3,5),(3,6), (3,7),(4,1),(4,2),(4,4),(4,6),(4,7),(5,1),(5,2),(5,3),(5,5),(5,6), (5,7),(6,0),(6,2),(6,3),(6,4),(6,5),(6,8),(7,0),(7,1),(7,2),(7,6), (7,7),(8,0),(8,1),(8,2),(8,3),(8,5),(8,6)] solvedBoardElements :: [BoardElement] solvedBoardElements = [((0,0),5),((0,1),3),((0,2),4),((0,3),6),((0,4),7),((0,5),8),((0,6),9), ((0,7),1),((0,8),2),((1,0),6),((1,1),7),((1,2),2),((1,3),1),((1,4),9), ((1,5),5),((1,6),3),((1,7),4),((1,8),8),((2,0),1),((2,1),9),((2,2),8), ((2,3),3),((2,4),4),((2,5),2),((2,6),5),((2,7),6),((2,8),7),((3,0),8), ((3,1),5),((3,2),9),((3,3),7),((3,4),6),((3,5),1),((3,6),4),((3,7),2), ((3,8),3),((4,0),4),((4,1),2),((4,2),6),((4,3),8),((4,4),5),((4,5),3), ((4,6),7),((4,7),9),((4,8),1),((5,0),7),((5,1),1),((5,2),3),((5,3),9), ((5,4),2),((5,5),4),((5,6),8),((5,7),5),((5,8),6),((6,0),9),((6,1),6), ((6,2),1),((6,3),5),((6,4),3),((6,5),7),((6,6),2),((6,7),8),((6,8),4), ((7,0),2),((7,1),8),((7,2),7),((7,3),4),((7,4),1),((7,5),9),((7,6),6), ((7,7),3),((7,8),5),((8,0),3),((8,1),4),((8,2),5),((8,3),2),((8,4),8), ((8,5),6),((8,6),1),((8,7),7),((8,8),9)] main :: IO () main = print (sudoku inputBoard == solvedBoard) sudoku :: Board -> Board sudoku [] = [] sudoku b = let bde = fst (toElements b) cd = snd (toElements b) allboards = sudokuElements [bde] cd in fromElements (head allboards) --sudoku b --| b == inputBoard = solvedBoard --| otherwise = error "sudoku not implemented" sudokuElements :: [[BoardElement]] -> [Coords] -> [[BoardElement]] sudokuElements a [] = a sudokuElements [] _ = [] sudokuElements (be:bes) (cd:cds) = let xs = validVals be cd temp = [[(cd,x)] | x <- xs] in sudokuElements temp cds -- | head bes == inputBoardElements && empty == inputBoardEmpty = -- [solvedBoardElements] -- | otherwise = error "sudokuElements not implemented" validVals :: [BoardElement] -> Coords -> [Int] validVals bes rc | bes == tail solvedBoardElements && rc==(8,6) = [1] | bes \\ solvedBoardElements == [] = [1..9] | otherwise = [] toElements :: Board -> ([BoardElement],[Coords]) toElements b | b==inputBoard = (inputBoardElements, inputBoardEmpty) | otherwise = error "toElements not implemented" fromElements :: [BoardElement] -> Board fromElements bes | sort bes == solvedBoardElements = solvedBoard | otherwise = error "fromElements not implemented"
The issue is that allBoards/the call to sudokuElements is returning an empty list. Without seeing the entire program, it's hard to give you an exact reason why this might be. I recommend avoiding the use of head in general as it is a partial function. Instead, use pattern matching. In your case, this fromElements (head allBoards) can be rewritten as case allBoards of [] -> error "allBoards returned an empty list." -- Or whatever (first:_) -> fromElements first
Haskell: Exception <<loop>> on recursive data entry
So I'm trying to make a little program that can take in data captured during an experiment, and for the most part I think I've figured out how to recursively take in data until the user signals there is no more, however upon termination of data taking haskell throws Exception: <<loop>> and I can't really figure out why. Here's the code: readData :: (Num a, Read a) => [Point a] -> IO [Point a] readData l = do putStr "Enter Point (x,y,<e>) or (d)one: " entered <- getLine if (entered == "d" || entered == "done") then return l else do let l = addPoint l entered nl <- readData l return nl addPoint :: (Num a, Read a) => [Point a] -> String -> [Point a] addPoint l s = l ++ [Point (dataList !! 0) (dataList !! 1) (dataList !! 2)] where dataList = (map read $ checkInputData . splitOn "," $ s) :: (Read a) => [a] checkInputData :: [String] -> [String] checkInputData xs | length xs < 2 = ["0","0","0"] | length xs < 3 = (xs ++ ["0"]) | length xs == 3 = xs | length xs > 3 = ["0","0","0"] As far as I can tell, the exception is indication that there is an infinite loop somewhere, but I can't figure out why this is occurring. As far as I can tell when "done" is entered the current level should simply return l, the list it's given, which should then cascade up the previous iterations of the function. Thanks for any help. (And yes, checkInputData will have proper error handling once I figure out how to do that.)
<<loop>> basically means GHC has detected an infinite loop caused by a value which depends immediately on itself (cf. this question, or this one for further technical details if you are curious). In this case, that is triggered by: else do let l = addPoint l entered This definition, which shadows the l you passed as an argument, defines l in terms of itself. You meant to write something like... else do let l' = addPoint l entered ... which defines a new value, l', in terms of the original l. As Carl points out, turning on -Wall (e.g. by passing it to GHC at the command line, or with :set -Wall in GHCi) would make GHC warn you about the shadowing: <interactive>:171:33: warning: [-Wname-shadowing] This binding for ‘l’ shadows the existing binding bound at <interactive>:167:10 Also, as hightlighted by dfeuer, the whole do-block in the else branch can be replaced by: readData (addPoint l entered) As an unrelated suggestion, in this case it is a good idea to replace your uses of length and (!!) with pattern matching. For instance, checkInputData can be written as: checkInputData :: [String] -> [String] checkInputData xs = case xs of [_,_] -> xs ++ ["0"] [_,_,_] -> xs _ -> ["0","0","0"] addPoint, in its turn, might become: addPoint :: (Num a, Read a) => [Point a] -> String -> [Point a] addPoint l s = l ++ [Point x y z] where [x,y,z] = (map read $ checkInputData . splitOn "," $ s) :: (Read a) => [a] That becomes even neater if you change checkInputData so that it returns a (String, String, String) triple, which would better express the invariant that you are reading exactly three values.
Parse error in pattern x * y (of case statement)
I have this code: module BalancedTwoDozenMultDrill where import BalancedTwoDozenLib myRandoms :: Int -> IO [Int] myRandoms n = let x = 24^n `div` 2 in randomRs (-x,x) <$> getStdGen drill :: [Int] -> IO () drill (x:y:rs) = do putStr $ showInt x ++ " × " ++ showInt y ++ " = " a <- getLine case a of "" -> return () showInt (x * y) -> do -- <= here putStrLn "Correct" drill rs _ -> do putStrLn $ "Wrong; " ++ showInt (x * y) drill rs main :: IO [Int] main = drill =<< myRandoms =<< readLn and get error: BalancedTwoDozenMultDrill.hs:11:18: Parse error in pattern: x * y However, replacing part of the case statement with: -- ...stuff let i = showInt (x * y) case a of "" -> return () i -> do -- stuff... Makes it parse (it goes to “not in scope” errors, which I can fix). The only reason I see for the first fragment being wrong is that there is function application going on. Is it true that I can't use ordinary function application for the alternatives in a case statement?
When you have a pattern in a case statement, it has to follow the same rules as that in pattern matching on function arguments. Only literals, constructors, and the wildcard _ can be matched on, not function applications. Instead, you could do something more like a <- getLine let xyStr = showInt (x * y) -- Avoid recomputation with a let binding when (not $ null a) $ do if a == xyStr then do putStrLn "Correct" drill rs else do putStrLn $ "Wrong; " ++ xyStr drill rs You'll need to import when from Control.Monad, though. The reason why you have to follow the same rules in case statements as in pattern matching in function definitions is because the compiler actually converts something like head :: [a] -> a head (x:xs) = x head _ = error "Prelude.head: empty list" Into head :: [a] -> a head list = case list of (x:xs) -> x _ -> error "Prelude.head: empty list" The only reason we have the former version is convenience, it often makes for prettier looking code. This link should be able to give you a more thorough explanation as to what is and isn't valid pattern matching constructs. The other problem you had was trying to replace showInt (x * y) with i where let i = showInt (x * y). When you do this, you first bind the value showInt (x * y) to the name i, then in your case statement you have the patterns "" -> ... i -> ... _ -> ... So now your pattern is i, and it will act like a catch-all pattern after "". This rebinds the name i for the scope of that case statement. A good rule to keep in mind is that you can't pattern match against a value obtained at run time, you have to check with equality or other comparison operations.
Although an answer already accepted I'd just mention there is a bit tricky way how use a boolean expressions in a case expression - by using guards: case () of _ | a == "" -> return () | showInt (x * y) -> do -- <= here putStrLn "Correct" drill rs | otherwise -> do putStrLn $ "Wrong; " ++ showInt (x * y) drill rs
haskell : How to report an error for my function
this is an expansion to my last question here: basic haskell : Copying elements however when an invalid input is added then I want it to print out an error message saying "negative value" or something similar. Is this possible in haskell? working code: copy :: Int->a->[a] copy 0 _ = [] copy y a = [a]++(copy (y-1) a) final line: copy b c = error "negative value"
Because partial functions make me sad, I'd suggest doing something more along the lines of copy :: Int -> a -> Maybe [a] copy 0 _ = Just [] copy n a | n < 0 = Nothing | otherwise = fmap (a:) (copy (n-1) a) We've swapped out that if for a "guard" foo bar | baz = quux | ... is just foo bar = if baz then quux else ... Note that I also changed your code a little, [a] ++ copy (y-1) a ====> fmap (a:) (copy (y-1) a) You can think of (:) as append. 1 : [2, 3] ==> [1, 2, 3] It's the preferred alternative to [1] ++ [2, 3]. Say it out loud as "cons", like "construct". We can write this with an operator section (a:) ==> \x -> a : x Next we use this wonky fmap function. Think of fmap like this fmap f Nothing = Nothing fmap f (Just x) = Just (f x) So it unwraps a Just and applies a function before rewrapping the result. So our final code returns Nothing if our number is negative, otherwise, just the list. Why aren't I recommending error? Well because error will blow up your whole program with pretty minimal information and it's a bad idea to try to catch it. Haskell doesn't even mandate that it's possible to do so, GHC just implements error in such a way that it's possible. In other words, you have little chance to recover. This isn't a big deal for 10 lines of code, but I've spent upwards of 6 hours searching for the offending call to a function using error. It's much faster to debug and more idiomatic haskell.
You can do this with guards copy :: Int -> a -> [a] copy n x | n < 0 = error "negative value" | n == 0 = [] | otherwise = x : copy (n - 1) x However, if this fails then it will likely crash your program. A better way is to use the Maybe type: copySafe :: Int -> a -> Maybe [a] copySafe n x | n < 0 = Nothing | otherwise = Just (copy n x) Then you can use it as main = do putStrLn "Enter a number:" nStr <- getLine let n = read nStr :: Int maybeXs = copySafe n n case maybeXs of Nothing -> putStrLn "You entered a negative number!" Just xs -> print xs This style forces you to consider both cases of copySafe, either it can fail on a negative value or it can return a valid list. It doesn't crash your program and the error handling is enforced by the type system.
look at http://www.haskell.org/haskellwiki/Error_vs._Exception for example copy b c = if c > b then error "negativ value"