Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 在给定索引处使用元素更新列表_Haskell - Fatal编程技术网

Haskell 在给定索引处使用元素更新列表

Haskell 在给定索引处使用元素更新列表,haskell,Haskell,是否有这样的功能: update :: a -> Int -> [a] -> Maybe [a] 这样,它将使用给定索引处的元素更新列表,或者在索引超出边界时返回Nothing 例如: > update 9 1 [3,4,5] Just [3,9,5] > update 4 2 [3,4,5] Just [3,4,4] > update 6 5 [3,4,5] Nothing 它可以写得相当残酷: update val idx l = if idx

是否有这样的功能:

update :: a -> Int -> [a] -> Maybe [a]
这样,它将使用给定索引处的元素更新列表,或者在索引超出边界时返回
Nothing

例如:

> update 9 1 [3,4,5]
Just [3,9,5]

> update 4 2 [3,4,5]
Just [3,4,4]

> update 6 5 [3,4,5]
Nothing

它可以写得相当残酷:

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
以不抛出错误,而是让它在
上运行,也可以改为
类型:

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)
update idx idx<0=无
更新u[]=无
更新val idx(h:t)=
如果idx==0,则只需$val:t
else(h:)(updateUnsafe val(idx-1)t)


在标准库中,我看不到任何函数可以解决这个问题。它可以非常残酷地编写:

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
以不抛出错误,而是让它在
上运行,也可以改为
类型:

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)
update idx idx<0=无
更新u[]=无
更新val idx(h:t)=
如果idx==0,则只需$val:t
else(h:)(updateUnsafe val(idx-1)t)


我在标准库中看不到任何函数可以解决这个问题,我会这样做。特别要注意的是,它不使用任何部分函数或不完整的模式匹配,即使在命中它们“永远”不会发生的地方也是如此。它还正确处理负索引的情况,立即返回
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
update::a->Int->[a]->可能[a]
更新y=go
哪里
go[]=Nothing——哎呀,调用的更新索引太大了
go i(x:xs)=案例i`compare`0 of
LT->Nothing--哎呀,叫“带负索引的更新”
EQ->Just(y:xs)
GT->(x:)更新y(pred i)xs

我会这样做。特别要注意的是,它不使用任何部分函数或不完整的模式匹配,即使在命中它们“永远”不会发生的地方也是如此。它还正确处理负索引的情况,立即返回
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
update::a->Int->[a]->可能[a]
更新y=go
哪里
go[]=Nothing——哎呀,调用的更新索引太大了
go i(x:xs)=案例i`compare`0 of
LT->Nothing--哎呀,叫“带负索引的更新”
EQ->Just(y:xs)
GT->(x:)更新y(pred i)xs

uhh,当这完全可以处理时,您为什么要故意抛出错误?例如,
update::a->Int->[a]->可能[a]
..->([a],Bool)
?嗯,我的意思是,你总是可以根据需要手动抛出一些东西,但它不属于
update
函数。很好的建议如果索引超出范围,为什么不直接返回原始列表呢?我不认为这比替换一个已经存在值的元素更模糊。(这与
take
如果请求大小大于参数的长度,则返回最长的列表的精神是一样的。)根据这一点,没有这样的函数,但答案是您需要的。@chepner我认为a可能更具原则性。通过检查Maybe,您可以随时从Maybe版本切换到自返回版本,但是如果您始终返回的唯一版本
[a]
,那么判断替换是否成功并不便宜。uhh,当这完全可以处理时,为什么要故意抛出错误?例如,
update::a->Int->[a]->可能[a]
…->([a],Bool)
?嗯,我的意思是,你总是可以根据需要手动抛出一些东西,但它不属于
update
函数。很好的建议如果索引超出范围,为什么不直接返回原始列表呢?我不认为这比替换一个已经存在值的元素更模糊。(这与
take
如果请求大小大于参数的长度,则返回最长的列表的精神是一样的。)根据这一点,没有这样的函数,但答案是您需要的。@chepner我认为a可能更具原则性。通过检查Maybe,您可以随时从Maybe版本转换为自动返回版本,但是如果您始终返回的唯一版本
[a]
,那么判断替换是否成功并不便宜。第一个版本相当危险,因为它将在无限列表上无限循环。我认为
Data.list.splitAt
在这里会有很大帮助。类似于(,[])的idx xs处的
大小写拆分->错误“;(before,:after)->before++val:after
第一个版本非常危险,因为它将在无限列表上无限循环。我认为
Data.list.splitAt
在这里会有很大帮助。类似于(,[])的idx xs处的
大小写拆分->错误“;(before,:after)->before++val:after
可能在顶部添加另一个子句,以便只处理一次负索引?可能在顶部添加另一个子句,以便只处理一次负索引?