从给定索引开始插入字符串
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
是要添加的文本,l
是 m
的长度,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"
我对 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
是要添加的文本,l
是 m
的长度,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"