<F: FunctorX>
int he kind extension
where
though
addOne
can also be redefined as:
func addOne<F>(_ fa: Kind<F, Int>) -> Kind<F, Int> where F : FunctorX, F.F == F {
return fa.fmap({b in return b + 1})
}
if it doesn't scale maybe we need
protocol Typeclass {
associatedtype F = Self
protocol FunctorX: Typeclass {
extension EitherPartial : FunctorX {
static func fmap<A, B>(_ fa: Kind<Kind<F, A>, A>, _ f: (A) -> B) -> Kind<Kind<F, A>, B> {
// implementation
}
}
// type class
protocol FunctorX {
associatedtype F
static func fmap<A, B>(_ fa: Kind<F, A>, _ f : (A) -> B) -> Kind<F, B>
}
// syntax for all kinds adhering to the type class
extension Kind {
func fmap<B>(_ f: (A) -> B) -> Kind<F, B> where F : FunctorX, F.F == F {
return F.fmap(self, f)
}
}
// Maybe Functor instance
extension ForMaybe : FunctorX {
typealias F = ForMaybe
class func fmap<A, B>(_ fa: Kind<ForMaybe, A>, _ f: (A) -> B) -> Kind<ForMaybe, B> {
return fa.fix().map(f)
}
}
// example of polymorphic function using syntax over kinds
func addOne<F: FunctorX>(_ fa: Kind<F, Int>) -> Kind<F, Int> where F.F == F {
return fa.fmap({b in return b + 1})
}
extension EitherPartial : FunctorX {
static func fmap<B, C>(_ fa: Kind<Kind<ForEither, A>, B>, _ f: @escaping (B) -> C) -> Kind<Kind<ForEither, A>, C> {
return Either<A, B>.fix(fa)
.fold({ a in Either<A, C>.left(a) },
{ b in Either<A, C>.right(f(b)) })
}
}
this actually worksextension EitherPartial : FunctorX { static func fmap<B, C>(_ fa: Kind<Kind<ForEither, A>, B>, _ f: @escaping (B) -> C) -> Kind<Kind<ForEither, A>, C> { return Either<A, B>.fix(fa) .fold({ a in Either<A, C>.left(a) }, { b in Either<A, C>.right(f(b)) }) } }