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
    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?
    Tomás Ruiz-López
    @truizlop
    It looks like that
    Raúl Raja Martínez
    @raulraja
    I noticed too that in SwiftZ they flatten the protocols with 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.
    Tomás Ruiz-López
    @truizlop
    I am checking and I have no clue how they can write a polymorphic function based on a typeclass. Also, their definition of Functor, Applicative, etc is similar to Functor3 that I suggested above, but IMO it is wrong since they have both A and B associated with the protocol
    Raúl Raja Martínez
    @raulraja
    right, what they seem to be doing is to apply the parameter to 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
    And AFAIK that would not allow for abstract functions depending on the evidence of type class instances which is clearly what we want to do here
    Víctor Galán
    @victorg1991
    I have to digest all this stuff, and try some things
    Tomás Ruiz-López
    @truizlop
    I think the way we have implemented things now (with separate instances) is probably the only way of having what we want, although it is a bit difficult to use. We'd need to find a way of providing the instances automatically as you were doing before in Arrow. This will eventually change when Swift supports Higher Kinds natively in the language. Since we've been stuck here for 2-3 weeks, I suggest we continue with the encoding we have for typeclasses right now, complete what's missing in the TO-DO list and publish a first release that we can use to build a few examples and see how easy/difficult is to use.
    Jorge Castillo
    @JorgeCastilloPrz
    Yeah agree
    Tomás Ruiz-López
    @truizlop
    Good morning people! It's been a long time since last time we wrote in this channel, but I'd like to give Bow a boost and try to launch an initial release this week or next at most. In the last few weeks I've been making some contributions to it (currently there are 4 PRs that need approval) and I think the library is in a state where it can be used, maybe not in its full potential, but at least to start receiving feedback and determine how to address usability issues. My intention is to create a few samples like the ones written in Kotlin and see how easy/hard they are to write.
    @victorg1991 could you help me with the publication of the initial release? I've done it some times in Cocoapods, but never used Carthage or SPM, so it would be nice to get your knowledge on this (and perhaps make a script to automate the release process).