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

时间:2018-05-01 17:52:41

标签: string haskell ghci

我对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)

2 个答案:

答案 0 :(得分:4)

let m = drop p m

是循环定义。它并不意味着“将m设置为小于m之前”,因为记住,在Haskell中修改变量是不可能的。相反,您忽略现有的m,并定义一个名为m的新变量,该变量根据其自身定义:永远无法完成的评估。这似乎是一个愚蠢的功能,但在其他情况下,根据自身定义值实际上非常有用,这就是语言允许的原因。

然后再次使用

犯同样的错误
t = addText t "test"

根据自身定义t

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

r = addText t "test"

此时您将遇到令人兴奋的新错误:由于类型默认规则,create的推断类型签名与addText的推断类型签名不匹配。如果您指定显式类型签名,或者内联create的定义,您将最终获得所需内容:

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

答案 1 :(得分:2)

像许多刚接触Haskell的人一样,您可以用命令式样式编写函数,其中更新变量。

然而,Haskell中的变量无法更新:您没有(重新)为变量赋值,您声明了一个变量。如果你写i = i + 1,你i的旧值,并向其添加1,你在这里声明i自己的术语,i = i + 1,意味着我们编写了一个无限深层的递归表达式i = ( ( (...) + 1) + 1) + 1

在您的功能中,您似乎更新了m

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,虽然由于懒惰这不会本身循环,如果m的值是必要的,我们将陷入无限递归。

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

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

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

Prelude> t = addText t "test"

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

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