Haskell 移位表

标签 haskell recursion

我想将列表向左移动 n 个元素。如果我想将顺序从 (x:xs) 更改为 (xs:x),为什么会出现错误?

shift n list@(x:xs)
    | n == 0 = list
    | otherwise = shift (n-1) (xs:x) -- (xs:x) error

Occurs check: cannot construct the infinite type: a ~ [a]

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

EDIT: As it was already mentioned, the correct term to use is rotate and not shift

最佳答案

Why do I get an error if I want to change the order from (x:xs) to (xs:x)?

因为类型不匹配。 (:) 的类型是 (:)::a -> [a] -> [a]。因此,它需要一个元素x(类型a)和一个包含其余元素的列表(类型[a])。您不能仅以相反的方式使用 (:)

您可以使用 (++) :: [a] -> [a] -> [a]将两个列表连接在一起。因此,我们可以通过从列表中删除 n 元素并将其与列表的前 n 元素连接到此来向左旋转。

<b>rotateL</b> :: Int -> [a] -> [a]
rotateL 0 list = list
rotateL n list | n < 0 = error "Negative index"
               | otherwise = <b>drop n list ++ take n list</b>

或者我们可以,比如 @YannVernier说,使用 splitAt :: Int -> [a] -> ([a], [a]) :

rotateL :: Int -> [a] -> [a]
rotateL 0 list = list
rotateL n list | n < 0 = error "Negative index"
               | otherwise = <b>lb ++ la</b>
    where (la, lb) = splitAt n list

或者不提及 list 参数:

rotateL :: Int -> [a] -> [a]
rotateL 0 = id
rotateL n | n < 0 = error "Negative index"
          | otherwise= <b>uncurry (flip (++)) . splitAt n</b>

Note: based on how your attempt, I think you actually want to rotate the list to the left, not shift it, since that would mean that you simply drop the first n elements, and fill it perhaps with some extra value.

Note: in case n is larger than the length of the list, then the rotateL will act as an identity function. That might not be the desired behavior. I leave it as an exercise to fix this edge-case.

关于Haskell 移位表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56108679/

相关文章:

haskell - 可以确保在安装 GHC 7.8 时安装分析库吗?

macos - OS X 上的 wxHaskell

java - 递归函数返回类型错误

php - 多层评论系统 Laravel

algorithm - 基于寄存器的编译器中递归函数的性能

haskell - 约束镜片

performance - Haskell 等函数式语言或 Scala 等混合语言中的函数开销

haskell - 奇怪的 Haskell/GHC 输出

javascript - 等待递归函数完成

使用递归返回字符串的Java方法