```package scalaz

trait Arrow[A[_, _]] {
val category: Category[A]

def arrow[B, C](f: B => C): A[B, C]

def first[B, C, D](a: A[B, C]): A[(B, D), (C, D)]

def second[B, C, D](a: A[B, C]): A[(D, B), (D, C)]
}

object Arrow {
import Scalaz._

implicit def Function1Arrow: Arrow[Function1] = new Arrow[Function1] {
val category = Category.Function1Category

def arrow[B, C](f: B => C) = f

def first[B, C, D](a: B => C) =
(bd: (B, D)) => (a(bd._1), bd._2)

def second[B, C, D](a: B => C) =
(db: (D, B)) => (db._1, a(db._2))
}

implicit def PartialFunctionArrow: Arrow[PartialFunction] = new Arrow[PartialFunction] {
val category = Category.PartialFunctionCategory

def arrow[B, C](f: B => C) = {
case b => f(b)
}

def first[B, C, D](a: PartialFunction[B, C]) = {
case (b, d) if a isDefinedAt b => (a(b), d)
}

def second[B, C, D](a: PartialFunction[B, C]): PartialFunction[(D, B), (D, C)] = {
case (d, b) if a isDefinedAt b => (d, a(b))
}
}

implicit def KleisliArrow[M[_]: Monad]: Arrow[({type λ[α, β]=Kleisli[M, α, β]})#λ] = new Arrow[({type λ[α, β]=Kleisli[M, α, β]})#λ] {
val category = Category.KleisliCategory

def arrow[B, C](f: B => C) = ☆(f(_) η)

def first[B, C, D](a: Kleisli[M, B, C]) = ☆ {
case (b, d) => a(b) ∘ ((_, d))
}

def second[B, C, D](a: Kleisli[M, B, C]) = ☆ {
case (d, b) => a(b) ∘ ((d, _))
}
}

implicit def CokleisliArrow[M[_]: Comonad]: Arrow[({type λ[α, β]=Cokleisli[M, α, β]})#λ] = new Arrow[({type λ[α, β]=Cokleisli[M, α, β]})#λ] {
val category = Category.CokleisliCategory

def arrow[B, C](f: B => C) = ★(r => f(r copure))

def first[B, C, D](a: Cokleisli[M, B, C]) = ★(a *** arrow(identity(_: D)) apply (_: M[(B, D)]))

def second[B, C, D](a: Cokleisli[M, B, C]) = ★(arrow(identity(_: D)) *** a apply (_: M[(D, B)]))
}
}

```