Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
    Paco
    @pakoito
    why does fmap in kind have different where than in addOne
    is it just convenience like in Kotlin?
    Raúl Raja Martínez
    @raulraja
    because in the kind extension F is not a type argument of the function but a type in the scope
    So I can't constrain it like <F: FunctorX> int he kind extension
    addOne can be expressed in terms of where though
    Paco
    @pakoito
    what puts F in scope in the kind extension?
    I'm learning swift :D
    Raúl Raja Martínez
    @raulraja
    F, A are the type args in Kind
    so you can access them by name
    in the body of the extension
    Paco
    @pakoito
    oh, there's no need to have them in the header
    good
    Raúl Raja Martínez
    @raulraja
    that is why extensions have no type args
    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})
    }
    Paco
    @pakoito
    :thumbsup:
    now if there wwas only a way of aliasing that
    can you try with multiple typeclass restrictions on a single function
    do you have to declare F.F == F for each?
    or is it structural?

    if it doesn't scale maybe we need

    protocol Typeclass {
    associatedtype F = Self

    protocol FunctorX: Typeclass {

    I'm going to bed now
    night!
    Raúl Raja Martínez
    @raulraja
    night
    Tomás Ruiz-López
    @truizlop
    this looks very promising
    I'm going to try a few things and come back with comments
    Tomás Ruiz-López
    @truizlop
    as I mentioned last night, this works for 1 argument type constructors, but fails for more complex ones
    to provide Functor for Either with this approach, we need to extend EitherPartial, but then the compiler gets confused:
    extension EitherPartial : FunctorX {
        static func fmap<A, B>(_ fa: Kind<Kind<F, A>, A>, _ f: (A) -> B) -> Kind<Kind<F, A>, B> {
            // implementation
        }
    }
    this is the suggestion for fmap from the tools
    which is wrong of course
    Juan Cazalla Estrella
    @juancazalla
    I think that the problem here is associatedType F == Self
    try moving it to the extension @truizlop
    I mean, using the first @raulraja shared
    Tomás Ruiz-López
    @truizlop
    wait, I think I managed to solve it
    Juan Cazalla Estrella
    @juancazalla
    // 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})
    }
    Tomás Ruiz-López
    @truizlop
    it is correct, but we need to fix the letters inferred by the compiler
    this actually works
    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)) })
        }
    }
    but we need to fix the stub provided by the compiler
    the issue is that the Kind extension stops working
    Juan Cazalla Estrella
    @juancazalla
    nice
    Juan Cazalla Estrella
    @juancazalla
    this actually works
    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)) })
        }
    }
    it doesn’t work for me :S
    Tomás Ruiz-López
    @truizlop
    maybe I changed something else
    in any case, I am experiencing 2 more problems
    1st when I try to extend another type as FunctorX, it says "Redundant conformance of Kind<F, A> to protocol FunctorX"
    2nd when I try to extend a type with 3 argument types, it cannot resolve the second argument
    let's say I have 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"
    Tomás Ruiz-López
    @truizlop
    since all the "Partial" classes are typealiases over Kind, the compiler thinks everything is Kind<F, A>
    Raúl Raja Martínez
    @raulraja
    could theses issue be related to the fact that kinds are now encoded in bow as actual typealiases and not new types?