gpt4 book ai didi

Haskell:预期的懒惰,为什么要评估?

转载 作者:行者123 更新时间:2023-12-03 07:41:11 26 4
gpt4 key购买 nike

我有一个功能 sideH这冒着 Prelude.head [] 的风险.因此,我使用Maybe来编写它,以避免这种情况:

sideH :: Residue -> Maybe (Atom, Atom)
sideH res
-- Make sure the elements exist
| nits /= [] && cars /= [] && oxys /= [] = Just (newH1, newH2)
| otherwise = Nothing where
...

以上完全按预期工作,没有错误。现在,在调用 sideH 的函数中(这不是 do 构造),我必须处理 sideH 的情况返回 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

如果我尝试评估 newH1PosnewH2PosnewH = Nothing ,它会失败,因为 fromJust Nothing是一个错误。但是,我希望这永远不会发生。我期待 callerFunc评估 newHs ,即 Just somethingNothing .如果是 Nothing ,然后是 callerFunc将进入下一步而不评估 newH1PosnewH2Pos .情况似乎并非如此。我得到一个 *** Exception: Maybe.fromJust: Nothing错误正是我所期望的 newHs返回 Nothing .

我被要求提供更多代码。我试图想出一个重现错误的最小情况,但与此同时,这里是完整的问题 callerFunc代码。
-- 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)

我知道这是一个痛苦的代码转储。我正在努力减少它。

最佳答案

这个问题的答案(在评论中提出)不适合评论:“我不确定在这里如何使用模式匹配来删除这些 if 语句。”。

像这样,例如,尽管仍然存在一些代码异味,但可以通过一些额外的重构来改进:

sideH :: Residue -> Maybe (Atom, Atom)
sideH res = case (nits, cars, oxys) of
(_:_, _:_, _:_) -> Just (newH1, newH2)
_ -> Nothing
where
...

如果你有灵活的道德,你可以尝试这样的事情:
sideH :: Residue -> Maybe (Atom, Atom)
sideH res = do
_:_ <- return nits
_:_ <- return cars
_:_ <- return oxys
return (newH1, newH2)
where
...

同样,如果有更多的上下文和代码可用于提出建议,那么这两个代码示例可能会改进大约十倍。

关于Haskell:预期的懒惰,为什么要评估?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9425437/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com