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)) }) } }
class Three<A, B, C> : Kind3<ForThree, A, B, C>
and typealias ThreePartial<A, B> = Kind2<ForThree, A, B>
extension ThreePartial : FunctorX {
static func fmap<C, D>(_ fa: Kind<Kind<Kind<ForThree, A>, B>, C>, _ f: @escaping (C) -> D) -> Kind<Kind<Kind<ForThree, A>, B>, D> {
// Implementation
}
}
this says "Use of undeclared type B"
associatedtype
and they make the extension implement the functions but not the actual protocols themselves. Not sure how they can do ad hoc polymorphism then or if their type classes are just syntax over data types.
Functor3
that I suggested above, but IMO it is wrong since they have both A
and B
associated with the protocol
Any
in order. So the Bifunctor
extensions which does not implement the protocol declare values for A, B etc which they don't have to fill in in other extensions https://github.com/typelift/Swiftz/blob/master/Sources/Swiftz/EitherExt.swift#L14