使用给定索引的元素更新列表

时间:2019-04-05 21:22:59

标签: haskell

有这样的功能吗?

<div id="wrapper">
  <header>
    <h1>Nature Walk</h1>
  </header>
  <ul id="dot">
    <nav>
      <li><a href="home.html">Home</a></li>
      <li><a href="login.html">Login</a></li>
      <li><a href="Amenities.html">Amenities</a></li>
      <li><a href="eForms.html">eForms</a></li>
    </nav>
  </ul>
</div>

是否将使用给定索引的元素来更新列表,或者如果索引超出边界,则返回update :: a -> Int -> [a] -> Maybe [a]

例如:

Nothing

2 个答案:

答案 0 :(得分:2)

我会这样做。特别要注意的是,它甚至不使用任何“部分”功能或不完整的模式匹配,即使在碰到它们的地方也不会“发生”。它还可以正确处理负索引的情况,立即返回Nothing而不是永远循环。

update :: a -> Int -> [a] -> Maybe [a]
update y = go
  where
    go _ [] = Nothing -- whoops, called update with too large an index
    go i (x:xs) = case i `compare` 0 of
      LT -> Nothing -- whoops, called update with a negative index
      EQ -> Just (y:xs)
      GT -> (x:) <$> update y (pred i) xs

答案 1 :(得分:0)

它可以写得很残酷:

update val idx l =
  if idx >= length l || idx < 0
  then Nothing
  else updateUnsafe val idx l

updateUnsafe _ _ [] = error "Empty List"
updateUnsafe val idx (h:t) =
  if idx == 0 then val:t
  else h:(updateUnsafe val (idx - 1) t)

或者尾递归:

updateUnsafe val idx = reverse . go [] val idx where
  go acc _ _ [] = acc
  go acc v i (h:t) = go ((if i == 0 then v else h) : t) v (i - 1) t

但是,当我们获得永无止境的列表时,这两种方法都会无限循环,这种情况可以在第一种情况下解决。我们可能会重写updateUnsafe而不是抛出错误,而是让它对Maybe类型进行操作:

update _ idx _ | idx < 0 = Nothing
update _ _ [] = Nothing
update val idx (h:t) =
  if idx == 0 then Just $ val:t
  else (h:) <$> (updateUnsafe val (idx - 1) t)

在标准instructions库中看不到任何可以解决该问题的函数