要旋转,您不需要任何丑陋的偏函数。这个奇怪Applicative
的会做的伎俩。
data Foo a t where
Cons :: (a -> q -> t) -> a -> Foo a q -> Foo a t
Nil :: t -> Foo a t
instance Functor (Foo a) where
fmap f (Cons g x xs) = Cons (\p q -> f (g p q)) x xs
fmap f (Nil q) = Nil (f q)
instance Applicative (Foo a) where
pure = Nil
liftA2 f (Nil t) ys = f t <$> ys
liftA2 f (Cons g x xs) ys = Cons (\a (q,b) -> f (g a q) b) x (liftA2 (,) xs ys)
您可以旋转一个Foo
:
rot :: Foo a t -> Foo a t
rot n@(Nil _) = n
rot (Cons g0 a0 as0) = go g0 a0 as0
where
go :: (a -> q -> t) -> a -> Foo a q -> Foo a t
go g a n@(Nil _) = Cons g a n
go g a (Cons h y ys) = Cons g y (go h a ys)
运行一个得到结果:
runFoo :: Foo a t -> t
runFoo (Nil t) = t
runFoo (Cons g x xs) = g x (runFoo xs)
把这一切放在一起,
rotate :: Traversable t => t a -> t a
rotate = runFoo . rot . traverse (\a -> Cons const a (Nil ()))
然后rotate [1..10] = [2..10] ++ [1]
。