List Haskell(:)和(+;+;)差异
我为这样的问题感到抱歉。我不太确定Haskell中List Haskell(:)和(+;+;)差异,list,haskell,syntax,List,Haskell,Syntax,我为这样的问题感到抱歉。我不太确定Haskell中:和++操作符的区别 x:y:[] = [x,y] 也 至于引起我这个问题的反向函数 reverse ::[a]->[a] reverse [] = [] reverse (x:xs) = reverse(xs)++[x] 为什么下面的方法不起作用 reversex ::[Int]->[Int] reversex [] = [] reversex (x:xs) = reversex(xs):x:[] 给出一个类型错误。:在列
:
和++
操作符的区别
x:y:[] = [x,y]
也
至于引起我这个问题的反向函数
reverse ::[a]->[a]
reverse [] = []
reverse (x:xs) = reverse(xs)++[x]
为什么下面的方法不起作用
reversex ::[Int]->[Int]
reversex [] = []
reversex (x:xs) = reversex(xs):x:[]
给出一个类型错误。:在列表中使用一个元素 ++附加两个列表 前者有两种类型
a -> [a] -> [a]
[a] -> [a] -> [a]
而后者则有类型
a -> [a] -> [a]
[a] -> [a] -> [a]
:
运算符被称为“cons”运算符,用于将head元素前置到列表中。因此,[]
是一个列表,x:[]
在x
前面加了一个空列表,使列表成为一个列表。然后,如果您选择consy:[x]
则会得到与y:x:[]
相同的列表[y,x]
++
运算符是列表串联运算符,它将两个列表作为操作数,并将它们“组合”到一个列表中。因此,如果您有列表[x]
和列表[y]
,那么您可以像这样连接它们:[x]+[y]
以获得[x,y
]
请注意,:
接受一个元素和一个列表,而++
接受两个列表
至于你的代码不起作用
reversex ::[Int]->[Int]
reversex [] = []
reversex (x:xs) = reversex(xs):x:[]
reverse函数的计算结果为一个列表。由于
:
运算符没有将列表作为其第一个参数,因此reverse(xs):x
无效。但是reverse(xs)++[x]
是有效的。与(++)
也许我想深入研究一下但是,
据我所知,如果你尝试连接
使用(++)
列出,例如:
[1, 2, 3] ++ [4, 5]
(++)
必须遍历完整的左侧列表。
看一看这张照片就知道了
更清楚了
(++) :: [a] -> [a] -> [a]
(++) [] ys = ys
(++) (x:xs) ys = x : xs ++ ys
因此,最好避免使用(++)
,因为每次调用
reverse(xs)+[x]
列表越来越大(或越来越小,具体取决于
无论如何,程序只需遍历另一个程序
(每次通话时都列出)
示例:
假设我通过连接实现了建议的反向
reversex ::[Int]->[Int]
reversex [] = []
reversex (x:xs) = reversex(xs)++[x]
反转列表[1,2,3,4]看起来有点像这样:
reversex [1, 2, 3, 4]
reversex [2, 3, 4] ++ [1]
reversex [3, 4] ++ [2] ++ [1]
reversex [4] ++ [3] ++ [2] ++ [1]
reversex [] ++ [4] ++ [3] ++ [2] ++ [1]
[] ++ [4] ++ [3] ++ [2] ++ [1]
[4] ++ [3] ++ [2] ++ [1]
[4, 3] ++ [2] ++ [1]
[4, 3, 2] ++ [1]
[4, 3, 2, 1]
使用cons运算符(:)的尾部递归强>
处理调用堆栈的一种方法是添加一个。
(仅仅添加一个累加器并不总是可能的,但大多数
一个人处理的递归函数是,因此可以
变成
在累加器的帮助下,可以做出这个例子
使用cons操作符(:)
工作。
累加器--ys
在我的示例中--累加当前结果并作为参数传递。因为有了累加器,我们现在可以
使用cons运算符通过附加
每次都是我们最初名单的负责人
reverse' :: (Ord a) => [a] -> [a] -> [a]
reverse' (x:xs) ys = reverse' xs (x:ys)
reverse' [] ys = ys
这里有一件事需要注意
累加器是一个额外的参数。我不知道哈斯克尔
提供默认参数,但在这种情况下最好,
因为您总是使用空列表调用此函数
就像累加器一样:reverse'[1,2,3,4][]
有很多关于尾部递归的文献,我
当然有很多类似的问题
堆栈交换/堆栈溢出。如果你发现任何错误,请纠正我
亲切问候,
编辑1:
威尔·内斯为你们中感兴趣的人指出了一些真正好答案的链接:
(:)
应用到x
和y
的thunk在语义上与x:y
相同,但占用更多内存。这对cons操作员来说是特别的
(和懒惰的构造函数)并且没有必要以任何方式强制执行
3.如果我用一个非常相似的函数求一个列表的整数的和,
通过模式或seq
功能进行严格评估
如果使用得当,将防止堆栈过大。e、 g:
sumUp' :: (Num a, Ord a) => [a] -> a -> a
sumUp' (x:xs) !y = reverse' xs (x + y)
sumUp' [] y = y
注意y前面的砰砰声。我在ghci试过了
占用更少的内存。
cons
倾向于使用类型构造函数而不是运算符。这里的示例是:
可以在let..in..
表达式中使用,但++
不能
let x : xs = [1, 2, 3] in x -- known as type deconstructing
将返回1,但
let [x] ++ [y, z] = [1, 2, 3] in x
将返回一个不在范围x中的错误变量
为了让它更简单,可以这样想cons
data List a = Cons a (List a) -- is equvalent with `data [a] = a:[a]`
此外,如果要使用cons反转阵列,请执行以下操作。下面是一个例子,知识来自Prolog
import Data.Function
reversex1 [] = []
reversex1 arr = reversex arr []
reversex [] arr = arr
reversex (x:xs) ys = reversex xs (x:ys)
main = do
reversex1 [1..10] & print
你可以稍微改变一下,得到正确的结果
reversex ::[Int]->[Int] # comment this line
reversex [] = []
reversex (x:xs) = reversex(xs) ++ x : []
对于遇到挑战的Lisp词汇表,“cons”构造一个新的列表节点,并将其添加到列表的开头。作为补充说明,您可以(也应该)不使用括号进行调用:
reverse(x:xs)=reverse xs++[x]
,否则在使用具有多个参数的函数时,您会被绊倒。不要调用func(arg)之类的函数
。那是可怜的哈斯克尔。始终调用函数,如func arg
。带有清晰空格的代码使代码更加自信和可读。@AJFarmarfunc-arg
确实比func(arg)
更正确,但我认为f(x)
通常比fx
更可读,因为它与大多数其他语言以及指定函数的数学方法相匹配。所以我想说“更自信、更具可读性”是一个观点问题。@icc97,上下文。在编写Haskell代码的上下文中,func(arg)
与使用Haskell从不延迟延迟构造函数的应用程序一样令人困惑(因为从来没有延迟构造函数)