From 62dd700be785c42f9e5ac9fbfeb1f35785289249 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Ruiz-L=C3=B3pez?= Date: Tue, 4 Dec 2018 11:17:33 +0100 Subject: [PATCH] Translate chapter 3.10 into Swift --- 3.10-ends-and-coends.md | 307 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 307 insertions(+) create mode 100644 3.10-ends-and-coends.md diff --git a/3.10-ends-and-coends.md b/3.10-ends-and-coends.md new file mode 100644 index 0000000..820b3d3 --- /dev/null +++ b/3.10-ends-and-coends.md @@ -0,0 +1,307 @@ +```Haskell +class Profunctor p where + dimap :: (c -> a) -> (b -> d) -> p a b -> p c d +``` +```swift +protocol Profunctor { + associatedtype P + + func dimap(_ pab : Kind2, _ f : @escaping (C) -> A, _ g : @escaping (B) -> D) -> Kind2 +} +``` +................ +```Haskell +dimap f id pbb :: p a b +``` +```swift +dimap(pbb, f, id) : Kind2 +``` +................ +```Haskell +dimap id f paa :: p a b +``` +```swift +dimap(paa, id, f) : Kind2 +``` +................ +```Haskell +dimap id f . alpha = dimap f id . alpha +``` +```swift +compose({ pab in dimap(pab, id, f)}, alpha) == + { pab in dimap(pab, f, compose(id, alpha)) } +``` +................ +```Haskell +forall a. p a a +``` +```swift +// No Rank-N types in Swift +// We have to introduce polymorphic function +protocol PolyFunction1 { + associatedtype P + + func apply() -> Kind2 +} +``` +................ +```Haskell +dimap f id . pi = dimap id f . pi +``` +```swift +compose({ pab in dimap(pab, f, id) }, pi.apply) == + { pab in dimap(pab, id, compose(f, pi.apply)) +``` +................ +```Haskell +dimap f idb . pib = dimap ida f . pia +``` +```swift +compose({ pab in dimap(pab, f, id) }, pi_b.apply) == + compose({ pab in dimap(pab, id, )}, pi_a.apply) +``` +................ +```Haskell +Profunctor p => (forall c. p c c) -> p a b +``` +```swift +func side(_ f : PolyFP, _ profunctor : ProfunctorP) -> Kind where + PolyFP : PolyFunction1, PolyFP.P == P, + ProfunctorP : Profunctor, ProfunctorP.P == P +``` +................ +```Haskell +pi :: Profunctor p => forall c. (forall a. p a a) -> p c c +pi e = e +``` +```Swift +protocol PolyFunction2 { + associatedtype P + + func apply(_ in : PolyFP) -> Kind2 where PolyFP : PolyFunction1, PolyFP.P == P +} + +class BasePolyFunction2

: PolyFunction2 { + func apply(_ in : PolyFP) -> Kind2 where PolyFP : PolyFunction1, PolyFP.P == P { + return in.apply() + } +} + +func pi(_ profunctor : ProfunctorP) -> BasePolyFunction2 { + return BasePolyFunction2

() +} +``` +................ +```Haskell +lambda :: Profunctor p => p a a -> (a -> b) -> p a b +lambda paa f = dimap id f paa + +rho :: Profunctor p => p b b -> (a -> b) -> p a b +rho pbb f = dimap f id pbb +``` +```swift +func lambda(_ paa : Kind2, _ f : @escaping (A) -> B, _ profunctor : ProfunctorP) -> Kind2 where +ProfunctorP : Profunctor, ProfunctorP.P == P { + return profunctor.dimap(paa, id, f) +} + +func lambda(_ pbb : Kind2, _ f : @escaping (A) -> B, _ profunctor : ProfunctorP) -> Kind2 where +ProfunctorP : Profunctor, ProfunctorP.P == P { + return profunctor.dimap(pbb, f, id) +} +``` +................ +```Haskell +type ProdP p = forall a b. (a -> b) -> p a b +``` +```swift +protocol ProdP { + associatedtype P + + func apply(_ f : @escaping (A) -> B) -> Kind2 +} +``` +................ +```Haskell +newtype DiaProd p = DiaProd (forall a. p a a) +``` +```swift +class DiaProd where PolyFP : PolyFunction1, PolyFP.P == P { + let paa : PolyFP +} +``` +................ +```Haskell +lambdaP :: Profunctor p => DiaProd p -> ProdP p +lambdaP (DiaProd paa) = lambda paa + +rhoP :: Profunctor p => DiaProd p -> ProdP p +rhoP (DiaProd paa) = rho paa +``` +```swift +class LambdaProdP : ProdP where + ProfunctorP : Profunctor, ProfunctorP.P == P, + PolyFP : PolyFunction1, PolyFP.P == P { + + let profunctor : ProfunctorP + let dia : DiaProd + + init(_ profunctor : ProfunctorP, _ dia : DiaProd) { + self.profunctor = profunctor + self.dia = dia + } + + func apply(_ f : @escaping (A) -> B) -> Kind2 { + return lambda(dia.paa, f, profunctor) + } +} + +func lambdaP(_ profunctor : ProfunctorP) -> (DiaProd) -> LambdaProdP

{ + return { dia in LambdaProdP(profunctor, dia)} +} + +class RhoProdP : ProdP where + ProfunctorP : Profunctor, ProfunctorP.P == P, + PolyFP : PolyFunction1, PolyFP.P == P { + + let profunctor : ProfunctorP + let dia : DiaProd + + init(_ profunctor : ProfunctorP, _ dia : DiaProd) { + self.profunctor = profunctor + self.dia = dia + } + + func apply(_ f : @escaping (A) -> B) -> Kind2 { + return rho(dia.paa, f, profunctor) + } +} +``` +................ +```Haskell +forall a. f a -> g a +``` +```swift +protocol FunctionK { + associatedtype F + associatedtype G + + func apply(_ f : Kind) -> Kind +} +``` +................ +```Haskell +exists a. p a a +``` +```swift +Kind2 +``` +................ +```Haskell +data Coend p = forall a. Coend (p a a) +``` +```swift +protocol Coend { + associatedtype P + + func paa() -> Kind2 +} +``` +................ +```Haskell +data SumP p = forall a b. SumP (b -> a) (p a b) +``` +```swift +protocol SumP { + associatedtype P + + func f(_ b : B) -> A + func pab() -> Kind2 +} +``` +................ +```Haskell +data DiagSum p = forall a. DiagSum (p a a) +``` +```swift +protocol DiagSum { + associatedtype P + + func paa() -> Kind2 +} +``` +................ +```Haskell +lambda, rho :: Profunctor p => SumP p -> DiagSum p +lambda (SumP f pab) = DiagSum (dimap f id pab) +rho (SumP f pab) = DiagSum (dimap id f pab) +``` +```swift +class LambdaDiagSum : DiagSum where + ProfunctorP : Profunctor, ProfunctorP.P == P, + ASumP : SumP, ASumP.P == P { + + let profunctor : ProfunctorP + let sump : ASumP + + init(_ profunctor : ProfunctorP, _ sump : ASumP) { + self.profunctor = profunctor + self.sump = sump + } + + func paa() -> Kind2 { + return profunctor.dimap(sump.pab, sump.f, id) + } +} + +func lambda(_ sum : ASumP, _ profunctor : ProfunctorP) -> LambdaDiagSum

{ + return LambdaDiagSum(profunctor, sum) +} + +class RhoDiagSum : DiagSum where + ProfunctorP : Profunctor, ProfunctorP.P == P, + ASumP : SumP, ASumP.P == P { + + let profunctor : ProfunctorP + let sump : ASumP + + init(_ profunctor : ProfunctorP, _ sump : ASumP) { + self.profunctor = profunctor + self.sump = sump + } + + func paa() -> Kind2 { + return profunctor.dimap(sump.pab, id, sump.f) + } +} + +func rho(_ sum : ASumP, _ profunctor : ProfunctorP) -> RhoDiagSum

{ + return RhoDiagSum(profunctor, sum) +} +``` +................ +```Haskell +(exists x. p x x) -> c ≅ forall x. p x x -> c +``` +```swift +(Kind2) -> C ≅ (BasePolyFunction1

) -> C +``` +................ +```Haskell +data Procompose q p a b where + Procompose :: q a c -> p c b -> Procompose q p a b +``` +```swift +class Procompose {} + +func apply(_ qac : Kind2, _ pcb : Kind2) -> Procompose { + ... +} +``` +................ +```Haskell +exists c. (q a c, p c b) +``` +```swift +(Kind2, Kind2) +```