Haskell中的旋转函数
我想在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]并不意味着
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
(<>) = (++)