Haskell中的旋转函数

Haskell中的旋转函数,haskell,recursion,pattern-matching,Haskell,Recursion,Pattern Matching,我想在Haskell中编写一个函数,将作为第二个参数给出的列表按第一个参数指示的位置数进行旋转。使用模式匹配,实现递归函数 我编写了以下函数: rotate :: Int -> [a] -> [a] rotate 0 [y]= [y] rotate x [y]= rotate((x-1) [tail [y] ++ head [y]]) 但是这个函数总是产生一个错误。有办法解决吗? 函数在运行时应执行以下操作: rotate 1 "abcdef" "bcdefa" [y]并不意味着

我想在Haskell中编写一个函数,将作为第二个参数给出的列表按第一个参数指示的位置数进行旋转。使用模式匹配,实现递归函数

我编写了以下函数:

rotate :: Int -> [a] -> [a]
rotate 0 [y]= [y]
rotate x [y]= rotate((x-1) [tail [y] ++ head [y]])
但是这个函数总是产生一个错误。有办法解决吗? 函数在运行时应执行以下操作:

rotate 1 "abcdef"
"bcdefa"

[y]
并不意味着“让
y
成为一个列表”。它的意思是“此参数是一个包含一个名为
y
的元素的列表”。您有正确的结构,但不需要在
y
周围加括号

rotate :: Int -> [a] -> [a]
rotate 0 y = y
rotate x y = rotate (x-1) (tail y ++ [head y])

我想你想要这样的东西:

rotate :: Int -> [a] -> [a]
rotate 0 x = x
rotate times (x:xs) = rotate (times - 1) (xs ++ [x])
TL&DR

rotate :: Int -> [a] -> [a]
rotate = drop <> take
首先,
实际上是
Monoid
类型类中
mappend
函数的内联版本

然后我们看到,类型签名中的
半群b=>
约束声明返回类型
b
也应该是
半群
类型类的成员。由于我们使用了
drop::Int->[a]->[a]
take::Int->[a]->[a]
,我们可以很快注意到
b
实际上是另一个具有类型签名的函数
[a]->[a]
,因此它是
半群
类型类的成员,当且仅当它是
b
,它恰好是
[a]
也是
半群
类型类的成员,并且是

instance Semigroup [a] where
        (<>) = (++)
实例半群[a]其中
() = (++)
到目前为止,一切都成立,但它是如何工作的

我们可以从类型签名推断如下:

  • (drop::Int->([a]->[a])(take::Int->([a]->[a]))
  • \n->(删除n:[a]->[a])(删除n:[a]->[a])
    ,这是
  • \n->\xs->(删除nxs::[a])(删除nxs::[a])
    ,这是
  • \n->\xs->(放下nxs)+(拿走nxs)

这基本上比使用递归
++
运算符将头作为单例列表添加到尾的末尾要好,因为它会产生O(n^2)时间复杂度。

好答案,但是,我认为提及模式匹配与部分函数(
)这可能是一个很好的补充。用不必要的偏解来回答投票数最高的问题。请不要破坏你的帖子。如果您认为您的问题没有用处或不再有用,则应将其删除,而不是编辑掉所有使其成为问题的数据。通过在Stack Exchange网络上发布,您已授予SE分发该内容的不可撤销权利(根据CC By-SA 3.0许可证)。根据SE政策,任何故意破坏行为都将被恢复。但是,您不能轻易地删除一个答案经过投票表决的问题。更不用说它是非部分的,与其他解决方案不同。:)
instance Semigroup [a] where
        (<>) = (++)