Haskell - 在n位置更改元素?编译错误?

时间:2015-09-12 15:25:56

标签: haskell

所以我有这个功能

listSet :: [a] -> Integer -> a -> [a]
listSet l n x = 
    let (xs,_:ys) = splitAt n l
    xs ++ x : ys

但是我收到了一个错误:

:25:9:在let绑定中解析错误:缺少必需'in'

我想要解决这个问题的原因是什么?

我的逻辑是否正确分割到第n个位置并在列表的开头添加一个元素?

对错误或代码的任何帮助都将不胜感激!

编辑:无论如何都要使这段代码无需将Integer更改为Int?

1 个答案:

答案 0 :(得分:5)

是的,你的想法是正确的 - 只有两个问题:

  • 正如Jubobs所说,如果您在in块之外使用let,则需要do,因为这是let ... in ...表达式(见下文)
  • 您有轻微的类型问题:splitAt想要Int
listSet :: [a] -> Int -> a -> [a]
listSet l n x = 
    let (xs,_:ys) = splitAt n l
    in xs ++ x : ys

这应该有效

当然,您的解决方案存在一些问题:

  • 如果n大于您的列表,则您的功能将失败(例如listSet [1..4] 5 99
  • ++对于较大的列表并不是非常有效 - 如果您继续splitAt的实施(见下文),则无法做到。

正如您所问:是的,有一种简单的方法:例如,您可以用明显的递归样式编写它 - 这甚至会删除++并且需要splitAt

listSet :: [a] -> Integer -> a -> [a]
listSet [] _ _ = []
listSet (_:xs) 0 y = y:xs
listSet (x:xs) n y = x:listSet xs (n-1) y

或者您可以将您的版本与genericSplitAt一起使用 - 但请注意上述问题