Haskell: La paresse attendue, pourquoi est-ce évaluée?
-
12-11-2019 - |
Question
J'ai une fonction sideH
qui couvre le risque de Prelude.head []
. Par conséquent, je l'ai écrit en utilisant peut-être, pour éviter ceci:
sideH :: Residue -> Maybe (Atom, Atom)
sideH res
-- Make sure the elements exist
| nits /= [] && cars /= [] && oxys /= [] = Just (newH1, newH2)
| otherwise = Nothing where
...
Ce qui précède fonctionne exactement comme prévu, sans erreur. Maintenant, dans la fonction qui appelle sideH
(ce qui n'est pas une construction de DO), je dois gérer la situation qui sideH
Retour 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
Si j'essaie d'évaluer newH1Pos
ou newH2Pos
lorsque newH = Nothing
, ça échouera parce que fromJust Nothing
est une erreur. Cependant, je m'attends à ce que cela ne se produise jamais. Je m'attends à la callerFunc
évaluer newHs
, qui est soit Just something
ou Nothing
. Si c'est Nothing
, puis le callerFunc
ira à sa prochaine étape sans jamais évaluer newH1Pos
ou newH2Pos
. Cela ne semble pas être le cas. Je reçois un *** Exception: Maybe.fromJust: Nothing
erreur exactement là où je m'attendrais newHs
rendre Nothing
.
On m'a demandé plus de code. J'essaie de trouver une situation minimale qui reproduit l'erreur, mais en attendant, voici le problème complet 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)
Je sais que c'est un vidage de code douloureux. J'essaye de le réduire.
Pas de solution correcte