【问题标题】:Puting a new element at the begining of the list将新元素放在列表的开头
【发布时间】:2021-08-16 05:16:28
【问题描述】:

大家好! 所以我的问题是我在这段代码中没有看到任何不好的地方。

type Name = String

type Val = Either Int Bool
type Env = [(Name, Val)]    

update :: Name -> Val -> Env -> Env -> Env
    update x v [] origi = (x,v): origi
    update x v ((x', v'):xs) origi
      | x == x'   = (x, v):xs
      | otherwise = (x', v') : update x v xs origi

但任何时候我调用它都会重复第一个元素。我相信它不会检查列表的最后一个元素,但我没有在我错过它的地方得到它。

所以我想在这里做什么。正在更新列表中的元素。但如果他们不在列表中。我想把它们放在开头。我知道把它们放在最后很容易。

【问题讨论】:

  • 为什么有两个Env参数?我只期待一个。
  • 一个是遍历原始lsit,一个是逐个元素遍历List
  • 我认为这不应该是函数外部接口的一部分。它可以使用辅助函数在内部处理该细节。
  • 我没看懂这个对不起:(
  • 所以我应该跳过将原始列表存储在变量中吗?

标签: haskell recursion


【解决方案1】:

如果我理解你所说的正确,你给update 输入了错误的类型。类型应该是

update :: Name -> Val -> Env -> Env

一个简单的实现是

import Data.Maybe (fromMaybe)

update :: Name -> Val -> Env -> Env
update name val env = 
    let newEnvIfAbsent = (name, val) : env
        tryToModify list = case list of
            [] -> Nothing
            (name', val') : rest -> if name' == name 
                                    then Just $ (name, val) : rest
                                    else fmap ((name', val') :) $ tryToModify rest
    in fromMaybe newEnvIfAbsent $ tryToModify env

非正式地,我们尝试修改env,方法是找到一对(name : val') 并将其替换为(name, val)。如果这不成功,我们改为将(name, val) 附加到env 的开头。

具有讽刺意味的是,我们可以通过避免使用Maybe 来稍微提高算法的性能(尽管不是它的渐近复杂度),如下所示:

update name val env =
    let newEnvIfAbsent = (name, val) : env
        tryToModify list = case list of
            [] -> ([], False)
            (name', val') : rest -> if name' == name
                                    then ((name, val) : rest, True)
                                    else let (rem, suc) = tryToModify rest
                                          in ((name', val') : rem, suc)
        (modifyResult, succeeded) = tryToModify env
    in if succeeded then modifyResult else newEnvIfAbsent

在第二个实现中,我们不必将有关成功或失败的信息传回堆栈。因此,我们不太容易受到堆栈溢出的影响。

【讨论】:

    猜你喜欢
    • 2015-05-11
    • 1970-01-01
    • 1970-01-01
    • 2019-12-29
    • 2021-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-09
    相关资源
    最近更新 更多