从给定索引开始插入字符串

Insert a string starting at a given index

我对 Haskell 完全陌生。我需要在可能已经非空的字符串的给定索引处插入给定字符串。

这就是我目前所拥有的。然而,在看似 运行 没有错误之后,当我询问 t 的值是什么时,ghci 只是无限期地挂起。

Haskell:

create = ("",0,0,"","")

addText (m,l,p,_,k) i = 
    let a = take p m
        m = drop p m
        full = a++i++m
    in (full, length full, p + length i, "", k)

其中 m 是要添加的文本,lm 的长度,p 是开始添加新字符串的索引

输出:

*Main> t = create

*Main> t

("",0,0,"","")

*Main> t = addText t "test"

*Main> t

(hangs)

let m = drop p m

是循环定义。并不是说"set m to be smaller than what m was before",因为记住,Haskell里面的变量是不可能修改的。相反,您忽略现有的 m,并定义一个名为 m 的新变量,根据自身定义:一个永远无法完成的评估。这似乎是一个愚蠢的功能,但在其他情况下,根据自身定义值实际上非常有用,这就是语言允许它的原因。

然后你又犯了同样的错误,

t = addText t "test"

根据自身定义 t

您可以使用唯一命名的变量来修复这两个错误,例如

r = addText t "test"

此时您将 运行 陷入令人兴奋的新错误:create 的推断类型签名与 addText 的推断类型签名不匹配,因为类型默认规则。如果你指定显式类型签名,或者内联create的定义,你最终会得到你想要的:

*Main> addText ("",0,0,"","") "test"
("test",4,4,"","")

像许多刚接触 Haskell 的人一样,您以 命令式[​​=43=] 风格编写函数,其中您 更新 变量。

Haskell 中的变量无法更新:您不(重新)分配 一个值给变量,您声明了一个变量。如果你写 i = i + 1,你 而不是 i 的旧值,并向它添加 1,你在这里声明 i 本身,所以 i = i + 1,意味着我们写了一个无限深的递归表达式 i = ( ( (...) + 1) + 1) + 1.

在你的函数中你似乎更新了 m:

addText (<b>m</b>, l, p, _, k) i = 
    let a = take p <b>m</b>
        <b>m</b> = drop p <b>m</b>
        full = a++i++<b>m</b>
    in (full, length full, p + length i, "", k)

所以你写了 m 本身,尽管由于懒惰,这不会 本身 循环,以防 [=18= 的值] 是必要的,我们会陷入无限递归。

通过使用一个新的变量,我们可以解决问题:

addText (<b>m</b>, l, p, _, k) i = 
    let a = take p <b>m</b>
        <b>z</b> = drop p <b>m</b>
        full = a++i++<b>z</b>
    in (full, length full, p + length i, "", k)

如果你这样写也会出现同样的现象:

Prelude> t = addText t "test"

您再次根据自身定义 t。因此,您最好使用另一个变量或常量:

Prelude> t = addText ("",0,0,"","") "test"