我想将列表向左移动n个元素。为什么我得到一个错误,如果我想的顺序更改(x:xs)
到(xs:x)
?
shift n list@(x:xs)
| n == 0 = list
| otherwise = shift (n-1) (xs:x) -- (xs:x) error
Run Code Online (Sandbox Code Playgroud)
进行检查:无法构造无限类型:a〜[a]
我不知道如何解释这个错误。也许有人可以帮助我。非常感谢你。
编辑:正如已经提到的,要使用的正确术语是旋转而不是平移
为什么我得到一个错误,如果我想的顺序更改
(x:xs)
到(xs:x)
?
因为类型不匹配。的类型(:)
是(:) :: a -> [a] -> [a]
。因此,它需要一个元素x
(类型a
)和一个包含其余元素的列表(类型[a]
)。您不能只是(:)
以相反的方式使用。
您可以使用将(++) :: [a] -> [a] -> [a]
两个列表连接在一起。因此,我们可以通过n
从列表中删除元素并将其与列表的第一个n
元素连接到此来向左旋转。
rotateL :: Int -> [a] -> [a]
rotateL 0 list = list
rotateL n list | n < 0 = error "Negative index"
| otherwise = drop n list ++ take n list
Run Code Online (Sandbox Code Playgroud)
或者我们可以像@YannVernier所说的那样使用splitAt :: Int -> [a] -> ([a], [a])
:
rotateL :: Int -> [a] -> [a]
rotateL 0 list = list
rotateL n list | n < 0 = error "Negative index"
| otherwise = lb ++ la
where (la, lb) = splitAt n list
Run Code Online (Sandbox Code Playgroud)
或不提及list
参数:
rotateL :: Int -> [a] -> [a]
rotateL 0 = id
rotateL n | n < 0 = error "Negative index"
| otherwise= uncurry (flip (++)) . splitAt n
Run Code Online (Sandbox Code Playgroud)
注意:基于您的尝试,我认为您实际上是想将列表向左旋转而不是将其移动,因为那将意味着您只是简单
drop
的第一个n
元素,并可能为其添加了一些额外的价值。
注意:如果
n
大于列表的长度,则rotateL
用作身份函数。那可能不是理想的行为。我将其保留为解决此问题的练习。
归档时间: |
|
查看次数: |
165 次 |
最近记录: |