Haskell: pigrizia prevista, perché è valutato?
-
12-11-2019 - |
Domanda
Ho una funzione sideH
che corre il rischio di Prelude.head []
. Quindi, l'ho scritto usando forse, per evitarlo:
sideH :: Residue -> Maybe (Atom, Atom)
sideH res
-- Make sure the elements exist
| nits /= [] && cars /= [] && oxys /= [] = Just (newH1, newH2)
| otherwise = Nothing where
...
Quanto sopra funziona esattamente come previsto, senza errore. Ora, nella funzione che chiama sideH
(che non è un costrutto DO), devo gestire la situazione che sideH
ritorna 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
Se provo a valutare newH1Pos
o newH2Pos
quando newH = Nothing
, fallirà perché fromJust Nothing
è un errore. Tuttavia, mi aspetto che questo non accada mai. Mi aspetto il callerFunc
valutare newHs
, che è nemmeno Just something
o Nothing
. Se è Nothing
, poi il callerFunc
andrà al suo prossimo passaggio senza mai valutare newH1Pos
o newH2Pos
. Questo non sembra essere il caso. Ottengo un *** Exception: Maybe.fromJust: Nothing
errore esattamente dove mi aspetterei newHs
ritornare Nothing
.
Mi è stato chiesto più codice. Sto cercando di trovare una situazione minima che riproduce l'errore, ma nel frattempo, ecco il completo problematico callerFunc
codice.
-- 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)
So che questo è un dump di codice doloroso. Sto provando a sbirciarlo.
Nessuna soluzione corretta