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
    not sure
    Raúl Raja Martínez
    @raulraja
    good one yeah this works
    that removes the need to type it again in the extension
    Paco
    @pakoito
    post an updated snippet when you have it ready
    I want to see it :)
    Raúl Raja Martínez
    @raulraja
    protocol FunctorX {
        associatedtype F = Self
        static func fmap<A, B>(_ fa: Kind<F, A>, _ f : (A) -> B) -> Kind<F, B>
    }
    
    extension Kind {
        func fmap<B>(_ f: (A) -> B) -> Kind<F, B> where F : FunctorX, F.F == F {
            return F.fmap(self, f)
        }
    }
    
    extension ForMaybe : FunctorX {
        class func fmap<A, B>(_ fa: Kind<ForMaybe, A>, _ f: (A) -> B) -> Kind<ForMaybe, B> {
            return fa.fix().map(f)
        }
    }
    
    func addOne<F: FunctorX>(_ fa: Kind<F, Int>) -> Kind<F, Int> where F.F == F {
        return fa.fmap({b in return b + 1})
    }
    Paco
    @pakoito
    F.F == F
    Raúl Raja Martínez
    @raulraja
    Except for the F.F == F this is how we wanted type classes in Kotlin to work
    Paco
    @pakoito
    is that sill necessary?
    Raúl Raja Martínez
    @raulraja
    yes
    Paco
    @pakoito
    both?
    Raúl Raja Martínez
    @raulraja
    yes because the compiler defers verification and there is no proof that conforming to a protocol maps your generic types to the protocol's ones
    Paco
    @pakoito
    okay
    Raúl Raja Martínez
    @raulraja
    Error:(32, 23) cannot convert value of type 'Kind<F, A>' to expected argument type 'Kind<_, _>'
    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