Haskell班次列表

Tab*_*koj 0 recursion haskell

我想将列表向左移动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]

我不知道如何解释这个错误。也许有人可以帮助我。非常感谢你。

编辑:正如已经提到的,要使用的正确术语是旋转而不是平移

Wil*_*sem 6

为什么我得到一个错误,如果我想的顺序更改(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用作身份函数。那可能不是理想的行为。我将其保留为解决此问题的练习。