List 在haskell中修改列表

List 在haskell中修改列表,list,haskell,List,Haskell,我有一份chars的清单 left = ['h', 'e', 'l', 'l', 'o'] 以及功能 typer :: [Char] -> Char -> [Char] typer left c = left ++ [c] 如果我在ghci中键入typer left'a',它会返回“helloa”,但如果我尝试读取left,它会返回“hello”。“a”在哪里?是否仍然可以使用该函数操纵左侧 Haskell函数是,这意味着它们不会有诸如修改变量之类的副作用。您的typer函数根据

我有一份chars的清单

left = ['h', 'e', 'l', 'l', 'o']
以及功能

typer :: [Char] -> Char -> [Char]
typer left c = left ++ [c]
如果我在
ghci
中键入
typer left'a'
,它会返回
“helloa”
,但如果我尝试读取
left
,它会返回
“hello”
“a”
在哪里?是否仍然可以使用该函数操纵
左侧

Haskell函数是,这意味着它们不会有诸如修改变量之类的副作用。您的
typer
函数根据其参数计算结果,但它实际上不(也不能)修改其参数

作为类比,在数学中,如果n是4,那么sqrt(n)是2,但即使计算了它的平方根,n仍然是4

如果要捕获函数调用的结果以便以后使用,请将其分配给另一个变量:

right = typer left 'a'
Haskell函数是,这意味着它们不会有诸如修改变量之类的副作用。您的
typer
函数根据其参数计算结果,但它实际上不(也不能)修改其参数

作为类比,在数学中,如果n是4,那么sqrt(n)是2,但即使计算了它的平方根,n仍然是4

如果要捕获函数调用的结果以便以后使用,请将其分配给另一个变量:

right = typer left 'a'

不!Haskell中的值是不可变的

您已将左侧的
声明为等于
“hello”
,并且始终等于
“hello”
。您可以在更近的范围内使用名为
left
的新标记隐藏特定的
left
值(例如具有名为
left
的函数参数,这将使全局定义的
left
在函数体中不可见)。但是,无法更改您声明的
值[1]

typer
返回一个新字符串,如果要保留
“helloa”
,则必须保留该值


[1] 在GHCi中,可以通过重新定义来隐藏以前的定义。这会悄悄地重新使用现有名称以指向新值。您不能在Haskell源文件中执行此操作。

不!Haskell中的值是不可变的

您已将左侧的
声明为等于
“hello”
,并且始终等于
“hello”
。您可以在更近的范围内使用名为
left
的新标记隐藏特定的
left
值(例如具有名为
left
的函数参数,这将使全局定义的
left
在函数体中不可见)。但是,无法更改您声明的
值[1]

typer
返回一个新字符串,如果要保留
“helloa”
,则必须保留该值


[1] 在GHCi中,可以通过重新定义以前的定义来隐藏它们。这会悄悄地重新使用现有名称以指向新值。不能在Haskell源文件中执行此操作。

通常不可以。通常,Haskell变量是不可变的。但是,有些库包含可变变量。例如,
Data.IORef
包含可更改的
IORef
。我将在下面解释如何使用它们,但作为一般规则,我建议不要使用它们,而是以更实用的方式编写代码

使用IORef,可以重写函数
typer

typer :: IORef [Char] -> Char -> IO()
typer left c = writeIORef left . (++[c]) =<< readIORef left

应产生所需的效果。

通常不,通常情况下,Haskell变量是不可变的。但是,有些库包含可变变量。例如,
Data.IORef
包含可更改的
IORef
。我将在下面解释如何使用它们,但作为一般规则,我建议不要使用它们,而是以更实用的方式编写代码

使用IORef,可以重写函数
typer

typer :: IORef [Char] -> Char -> IO()
typer left c = writeIORef left . (++[c]) =<< readIORef left

应该会产生所需的效果。

函数返回的值不是传递给它的参数。欢迎使用haskell,其中的值是不可变的。为什么希望函数修改
左侧的
?例如,为什么不
c
呢?函数返回的值不是传递给它的参数。欢迎来到haskell,这里的值是不可变的。为什么希望函数修改
左侧的
?为什么不以
c
为例?关于上一条语句:您可以在
do
块中使用连续的
let
语句重新定义变量,这些语句隐藏了相同名称的早期定义。在这方面,GHCi REPL类似于一个大的
do
块。。在
中,其中
在纯代码中块。对于最新的GHCi中的新手来说,这可能更令人困惑,因为绑定不再需要
let
关键字,而且看起来您在REPL中执行的是常规的Haskell声明。关于您的上一条语句:您可以在
do
块中使用连续的
let
语句重新定义变量,隐藏相同名称的早期定义。在这方面,GHCi REPL类似于一个大的
do
块。。在
中,其中
在纯代码中块。对于最新的GHCi中的新手来说,这可能更令人困惑,因为绑定不再需要
let
关键字,而且看起来您正在REPL中执行常规的Haskell声明。