首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Haskell:预期的懒惰,为什么要评估它?

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

Stack Overflow用户
提问于 2012-02-24 12:32:28
回答 1查看 234关注 0票数 2

我有一个运行Prelude.head []风险的函数sideH。因此,为了避免这种情况,我使用了“可能”来编写它:

代码语言:javascript
复制
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的情况

代码语言:javascript
复制
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

如果我在newH = Nothing时尝试计算newH1PosnewH2Pos,它将失败,因为fromJust Nothing是一个错误。然而,我希望这永远不会发生。我希望callerFunc评估newHs,它不是Just something就是Nothing。如果是Nothing,则callerFunc将进入下一步,而不计算newH1PosnewH2Pos。情况似乎并非如此。在我期望newHs返回Nothing的地方,我得到了一个*** Exception: Maybe.fromJust: Nothing错误。

我被要求提供更多的代码。我试图想出一个重现错误的最小情况,但同时,这里是完整的有问题的callerFunc代码。

代码语言:javascript
复制
-- 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)

我知道这是一个痛苦的代码转储。我正试着把它削下来。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-02-24 13:26:39

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

例如,像这样,尽管仍然有一些代码味道可能会通过一些额外的重构来改善:

代码语言:javascript
复制
sideH :: Residue -> Maybe (Atom, Atom)
sideH res = case (nits, cars, oxys) of
    (_:_, _:_, _:_) -> Just (newH1, newH2)
    _ -> Nothing
    where
    ...

如果你有灵活的道德规范,你可以试着这样做:

代码语言:javascript
复制
sideH :: Residue -> Maybe (Atom, Atom)
sideH res = do
    _:_ <- return nits
    _:_ <- return cars
    _:_ <- return oxys
    return (newH1, newH2)
    where
    ...

同样,如果有更多的上下文和代码可供推荐,这两个代码样本可能会改进十倍左右。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9425437

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档