Skip to content

Commit

Permalink
Add episode 10
Browse files Browse the repository at this point in the history
  • Loading branch information
stephencelis committed Apr 3, 2018
1 parent 25d5ec7 commit fff1067
Show file tree
Hide file tree
Showing 5 changed files with 304 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@

// extension Array {
// func flatMap<B>(_ f: @escaping (Element) -> [B]) -> [B] {
// }
// }

let csv = """
1,2,3,4
3,5,2
8,9,4
"""

csv
.split(separator: "\n")
.map { $0.split(separator: ",") }



// extension Optional {
// func flatMap<B>(_ f: @escaping (Element) -> B?) -> B? {
// }
// }

String.init(data: Data(), encoding: .utf8)
.map(Int.init)

let _: Int? = String.init(data: Data([55]), encoding: .utf8)
.flatMap(Int.init)

["1", "2", "buckle", "my", "shoe"]
.map(Int.init)

["1", "2", "buckle", "my", "shoe"]
.flatMap(Int.init)

csv.split(separator: "\n")
.flatMap { $0.split(separator: ",") }
.flatMap { Int($0) }
.reduce(0, +)




// flatMap : ((A) -> [B]) -> ([A]) -> [B]
// flatMap : ((A) -> B?) -> ( A?) -> B?

// flatMap : ((A) -> B?) -> ([A]) -> [B]



// flatMap : ((A) -> Array<B>) -> ( Array<A>) -> Array<B>
// flatMap : ((A) -> Optional<B>) -> (Optional<A>) -> Optional<B>

// flatMap : ((A) -> Optional<B>) -> ( Array<A>) -> Array<B>



// flatMap : ((A) -> M<B>) -> (M<A>) -> M<B>
// flatMap : ((A) -> M<B>) -> (M<A>) -> M<B>

// flatMap : ((A) -> B?) -> (M<A>) -> M<B>



[1, 2, 3]
.flatMap { $0 + 1 }



struct User {
let name: String
}

let users = [User(name: "Blob"), User(name: "Math")]
users
.map { $0.name }
users
.flatMap { $0.name }



extension Array {
func filterMap<B>(_ transform: (Element) -> B?) -> [B] {
var result = [B]()
for x in self {
switch transform(x) {
case let .some(x):
result.append(x)
case .none:
continue
}
}
return result
}
}



extension Array {
func compactMap<B>(_ transform: (Element) -> B?) -> [B] {
var result = [B]()
for x in self {
switch transform(x) {
case let .some(x):
result.append(x)
case .none:
continue
}
}
return result
}
}



func filterSome<A>(_ p: @escaping (A) -> Bool) -> (A) -> A? {
return { p($0) ? .some($0) : .none }
}


func filter<A>(_ p: @escaping (A) -> Bool) -> ([A]) -> [A] {
return { $0.filterMap(filterSome(p)) }
}


Array(0..<10)
|> filter { $0 % 2 == 0 }

enum Either<A, B> {
case left(A)
case right(B)
}



func partitionEither<A>(_ p: @escaping (A) -> Bool) -> (A) -> Either<A, A> {
return { p($0) ? .right($0) : .left($0) }
}





extension Array {
func partitionMap<A, B>(_ transform: (Element) -> Either<A, B>) -> (lefts: [A], rights: [B]) {
var result = (lefts: [A](), rights: [B]())
for x in self {
switch transform(x) {
case let .left(a):
result.lefts.append(a)
case let .right(b):
result.rights.append(b)
}
}
return result
}
}

func partition<A>(_ p: @escaping (A) -> Bool) -> ([A]) -> (`false`: [A], `true`: [A]) {
return {
let (lefts, rights) = $0.partitionMap(partitionEither(p))
return (lefts, rights)
}
}



func partitionMap<A, B, C>(_ p: @escaping (A) -> Either<B, C>) -> ([A]) -> (lefts: [B], rights: [C]) {
return { $0.partitionMap(p) }
}

let evenOdds = { $0 % 2 == 0 ? Either.left($0) : .right($0) }
partitionMap(evenOdds)

Array(1...10)
|> partitionMap(evenOdds)
|> (first <<< map)(square)
//: [See the next page](@next) for exercises!
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*:
# Algebraic Data Type: Exponents, Exercises

1. Define `filtered` as a function from `[A?]` to `[A]`.
*/
// TODO
/*:
2. Define `partitioned` as a function from `[Either<A, B>]` to `(left: [A], right: [B])`. What does this function have in common with `filtered`?
*/
// TODO
/*:
3. Define `partitionMap` on `Optional`.
*/
// TODO
/*:
4. Dictionary has `mapValues`, which takes a transform function from `(Value) -> B` to produce a new dictionary of type `[Key: B]`. Define `filterMapValues` on `Dictionary`.
// - Define `partitionMapValues` on `Dictionary`.
*/
// TODO
/*:
5. Define `partitionMapValues` on `Dictionary`.
*/
// TODO
/*:
6. Rewrite `filterMap` and `filter` in terms of `partitionMap`.
*/
/*:
7. Is it possible to define `partitionMap` on `Either`?
*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
@_exported import Foundation

precedencegroup ForwardApplication {
associativity: left
}

infix operator |>: ForwardApplication

precedencegroup ForwardComposition {
associativity: left
higherThan: ForwardApplication
}

infix operator >>>: ForwardComposition

public func |> <A, B>(x: A, f: (A) -> B) -> B {
return f(x)
}

public func >>> <A, B, C>(f: @escaping (A) -> B, g: @escaping (B) -> C) -> (A) -> C {
return { g(f($0)) }
}

public func zurry<A>(_ f: () -> A) -> A {
return f()
}

public func flip<A, B, C>(_ f: @escaping (A) -> (B) -> C) -> (B) -> (A) -> C {

return { b in { a in f(a)(b) } }
}

public func flip<A, C>(_ f: @escaping (A) -> () -> C) -> () -> (A) -> C {

return { { a in f(a)() } }
}


precedencegroup SingleTypeComposition {
associativity: left
higherThan: ForwardApplication
}

infix operator <>: SingleTypeComposition

public func <> <A>(f: @escaping (A) -> A, g: @escaping (A) -> A) -> (A) -> A {
return f >>> g
}

public func incr(_ x: Int) -> Int {
return x + 1
}

public func square(_ x: Int) -> Int {
return x * x
}

precedencegroup BackwardsComposition {
associativity: left
}
infix operator <<<: BackwardsComposition
public func <<< <A, B, C>(_ f: @escaping (B) -> C, _ g: @escaping (A) -> B) -> (A) -> C {
return { f(g($0)) }
}

public func second<A, B, C>(_ f: @escaping (B) -> C) -> ((A, B)) -> (A, C) {
return { pair in
return (pair.0, f(pair.1))
}
}

public func map<A, B>(_ f: @escaping (A) -> B) -> ([A]) -> [B] {
return { $0.map(f) }
}

public func first<A, B, C>(_ f: @escaping (A) -> B) -> ((A, C)) -> (B, C) {
return { pair in
(f(pair.0), pair.1)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='6.0' target-platform='macos' display-mode='rendered' executeOnSourceChanges='false'>
<pages>
<page name='01-Episode'/>
<page name='02-Exercises'/>
</pages>
</playground>
10 changes: 10 additions & 0 deletions 0010-a-tale-of-two-flat-maps/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
### [Point-Free](https://www.pointfree.co) Episode #10

### A Tale of Two Flat-Maps

> The most recent version of Swift, 4.1, has deprecated and renamed a particular overload of `flatMap`. We
> want to take a moment to understand what made this `flatMap` different from all the others, and explore
> generalizations of the operation to other structures.
This directory contains code from Point-Free Episode #10:
[A Tale of Two Flat-Maps](https://www.pointfree.co/episodes/ep10-a-tale-of-two-flat-maps)

0 comments on commit fff1067

Please sign in to comment.