Skip to content
This repository has been archived by the owner on Apr 5, 2022. It is now read-only.

Commit

Permalink
Merge pull request #16 from wayfair/big-monoid-update
Browse files Browse the repository at this point in the history
Big `monoid` update (and other changes)
  • Loading branch information
Peter Tomaselli authored Oct 3, 2019
2 parents 77ae90a + fa3c687 commit b922317
Show file tree
Hide file tree
Showing 15 changed files with 816 additions and 124 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ Carthage/
# Swift Package Manager
#
.build
.swiftpm/

# Jazzy
#
.docs/
.docs/
4 changes: 0 additions & 4 deletions .swiftlint.yml

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
//
// This source file is part of Prelude, an open source project by Wayfair
//
// Copyright (c) 2018 Wayfair, LLC.
// Licensed under the 2-Clause BSD License
//
// See LICENSE.md for license information
//

import Prelude

//
// Functions
//

// currying

func appendPunctuation(_ character: Character, toText text: String) -> String {
return "\(text)\(character)"
}
appendPunctuation("!", toText: "foo")

let appendQuestionMark = curry(appendPunctuation(_:toText:))("?")
appendQuestionMark("bar")

// function composition

func countCharacters(_ stringValue: String) -> Int {
return stringValue.count
}

let countQuestionCharacters = appendQuestionMark >>> countCharacters
countQuestionCharacters <| "hello"

"world" |> appendQuestionMark >>> countCharacters

countCharacters(appendQuestionMark(appendQuestionMark("123")))
countCharacters <<< appendQuestionMark <<< appendQuestionMark <| "123"

countCharacters
<<< appendQuestionMark
<<< appendQuestionMark
<| "1234"

//
// Monoids
//

[1, 2, 3] <> [4, 5, 6]
Array.empty <> [1, 2, 3] <> [4, 5, 6] <> .empty <> [7, 8, 9]

([1, 2, 3], ["a", "b"]) <> ([4, 5, 6], ["c", "d"])
([1, 2, 3], "ab", Last(value: 1.99)) <> ([4, 5, 6], "cd", Last(value: 99.99))

["a", "b", "c"].concat()

//
// use all the operators to make sure they play well together zone
//

struct M<A, B> { let run: (A) throws -> B }

func >>-<A, B, C>(_ lhs: M<A, B>, _ rhs: @escaping (B) -> M<A, C>) -> M<A, C> {
return .init { input in
let firstValue = try lhs.run(input)
let nextStep = rhs(firstValue)
return try nextStep.run(input)
}
}

extension M {
func map<C>(_ transform: @escaping (B) -> C) -> M<A, C> {
return .init { input in
try self.run(input) |> transform
}
}
}

typealias IO<B> = M<Void, B>

import Foundation

extension Date {
static var current: IO<Date> {
return .init { Date() }
}
}
extension DateFormatter {
static var myFormatter: IO<DateFormatter> {
return .init {
let formatter = DateFormatter()
formatter.dateStyle = .short
formatter.timeStyle = .short
return formatter
}
}
}
func doFormat(forDate date: Date) -> IO<String> {
return DateFormatter.myFormatter.map { $0.string(from: date) }
}

let x = Date.current >>- doFormat(forDate:)
x.run(())

func >-><A, B, C, D>(
_ lhs: @escaping (B) -> M<A, C>,
_ rhs: @escaping (C) -> M<A, D>) -> (B) -> M<A, D> {
return { value in lhs(value) >>- rhs }
}

func doPrint(_ stringValue: String) -> IO<Void> {
return .init { Swift.print(stringValue |> appendQuestionMark) }
}

let y = doFormat(forDate:) >-> doPrint
(Date.current >>- y).run(())
3 changes: 2 additions & 1 deletion Example/Prelude.playground/contents.xcplayground
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='6.0' target-platform='ios' executeOnSourceChanges='false'>
<playground version='6.0' target-platform='ios'>
<pages>
<page name='change-tracking'/>
<page name='prelude'/>
<page name='reducers'/>
<page name='refinement-types'/>
</pages>
Expand Down
66 changes: 6 additions & 60 deletions Prelude.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,6 @@
objectVersion = 50;
objects = {

/* Begin PBXAggregateTarget section */
66FB4F552194BFDF00D1B535 /* SwiftLint */ = {
isa = PBXAggregateTarget;
buildConfigurationList = 66FB4F582194BFDF00D1B535 /* Build configuration list for PBXAggregateTarget "SwiftLint" */;
buildPhases = (
66FB4F752194C00200D1B535 /* ShellScript */,
);
dependencies = (
);
name = SwiftLint;
productName = SwiftLint;
};
/* End PBXAggregateTarget section */

/* Begin PBXBuildFile section */
244559F92229775A00CFC0EB /* RefinementsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 244559F82229775A00CFC0EB /* RefinementsTests.swift */; };
244559FA2229775A00CFC0EB /* RefinementsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 244559F82229775A00CFC0EB /* RefinementsTests.swift */; };
Expand All @@ -31,6 +17,8 @@
24F05D00223074E3003502D0 /* Predicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F05CFE223074E3003502D0 /* Predicate.swift */; };
24F05D022231581F003502D0 /* PredicateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F05D012231581F003502D0 /* PredicateTests.swift */; };
24F05D032231581F003502D0 /* PredicateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F05D012231581F003502D0 /* PredicateTests.swift */; };
24F1FA6B22F3183500404CAB /* MonoidTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F1FA6A22F3183500404CAB /* MonoidTests.swift */; };
24F1FA6C22F3183500404CAB /* MonoidTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F1FA6A22F3183500404CAB /* MonoidTests.swift */; };
66541CC5217F6698001E088D /* Prelude.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66541CBB217F6698001E088D /* Prelude.framework */; };
6657D9B121AFA8960065E051 /* ChangeTracking.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66FE1E1121AC788200DF98C0 /* ChangeTracking.swift */; };
6657D9B221AFA8960065E051 /* Monoid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66FE1E0E21AC788200DF98C0 /* Monoid.swift */; };
Expand Down Expand Up @@ -80,6 +68,7 @@
249EE628222DC02200F93941 /* Nat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Nat.swift; sourceTree = "<group>"; };
24F05CFE223074E3003502D0 /* Predicate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Predicate.swift; sourceTree = "<group>"; };
24F05D012231581F003502D0 /* PredicateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PredicateTests.swift; sourceTree = "<group>"; };
24F1FA6A22F3183500404CAB /* MonoidTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MonoidTests.swift; sourceTree = "<group>"; };
66541CBB217F6698001E088D /* Prelude.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Prelude.framework; sourceTree = BUILT_PRODUCTS_DIR; };
66541CC4217F6698001E088D /* PreludeTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PreludeTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
6657D9A721AFA0B80065E051 /* Prelude.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Prelude.framework; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -167,6 +156,7 @@
isa = PBXGroup;
children = (
66FE1E1C21AC78A900DF98C0 /* ChangeTrackingTests.swift */,
24F1FA6A22F3183500404CAB /* MonoidTests.swift */,
24F05D012231581F003502D0 /* PredicateTests.swift */,
66FE1E1E21AC78A900DF98C0 /* PreludeTests.swift */,
66FE1E1F21AC78A900DF98C0 /* ReducersTests.swift */,
Expand Down Expand Up @@ -359,9 +349,6 @@
6657D9BB21AFA9850065E051 = {
CreatedOnToolsVersion = 10.1;
};
66FB4F552194BFDF00D1B535 = {
CreatedOnToolsVersion = 10.1;
};
};
};
buildConfigurationList = 66541CB3217F666E001E088D /* Build configuration list for PBXProject "Prelude" */;
Expand All @@ -381,7 +368,6 @@
6657D9A621AFA0B80065E051 /* Prelude macOS */,
66541CC3217F6698001E088D /* PreludeTests iOS */,
6657D9BB21AFA9850065E051 /* PreludeTests macOS */,
66FB4F552194BFDF00D1B535 /* SwiftLint */,
);
};
/* End PBXProject section */
Expand Down Expand Up @@ -417,27 +403,6 @@
};
/* End PBXResourcesBuildPhase section */

/* Begin PBXShellScriptBuildPhase section */
66FB4F752194C00200D1B535 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "if [ \"$CARTHAGE\" == 'YES' ]; then \n exit\nfi\n\nif command -v swiftlint >/dev/null; then\n swiftlint lint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
66541CB7217F6698001E088D /* Sources */ = {
isa = PBXSourcesBuildPhase;
Expand All @@ -464,6 +429,7 @@
66FE1E2321AC78A900DF98C0 /* ReducersTests.swift in Sources */,
244559F92229775A00CFC0EB /* RefinementsTests.swift in Sources */,
66FE1E2221AC78A900DF98C0 /* PreludeTests.swift in Sources */,
24F1FA6B22F3183500404CAB /* MonoidTests.swift in Sources */,
24F05D022231581F003502D0 /* PredicateTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -493,6 +459,7 @@
6657D9C721AFA99B0065E051 /* ChangeTrackingTests.swift in Sources */,
244559FA2229775A00CFC0EB /* RefinementsTests.swift in Sources */,
6657D9C821AFA99B0065E051 /* PreludeTests.swift in Sources */,
24F1FA6C22F3183500404CAB /* MonoidTests.swift in Sources */,
24F05D032231581F003502D0 /* PredicateTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -654,18 +621,6 @@
};
name = Release;
};
66FB4F562194BFDF00D1B535 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
};
name = Debug;
};
66FB4F572194BFDF00D1B535 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
};
name = Release;
};
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
Expand Down Expand Up @@ -714,15 +669,6 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
66FB4F582194BFDF00D1B535 /* Build configuration list for PBXAggregateTarget "SwiftLint" */ = {
isa = XCConfigurationList;
buildConfigurations = (
66FB4F562194BFDF00D1B535 /* Debug */,
66FB4F572194BFDF00D1B535 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 66541CB0217F666E001E088D /* Project object */;
Expand Down
19 changes: 17 additions & 2 deletions Sources/Prelude/ChangeTracking.swift
Original file line number Diff line number Diff line change
Expand Up @@ -172,13 +172,26 @@ public extension Changeable {
}

public extension Changeable {
/// write a `newValue` of type `V` at the keyPath `keyPath` in a receiver. As `self` is a value of type `Changeable<A>`, `self.hasChanged` will be updated to reflect whether this write actually caused a change inside of the `A`.
///
/// - Parameters:
/// - newValue: the value to potentially write. This value will be written if `!=` returns `true` when evaluated with the current value of the receiver at `keyPath`, and `newValue`, as arguments
/// - keyPath: the keyPath at which to potentially write a new value
mutating func write<V>(_ newValue: V, at keyPath: WritableKeyPath<A, V>) where V: Equatable {
self = flatMap(
Changeable.write(
newValue,
at: keyPath))
at: keyPath
)
)
}

/// write a `newValue` of type `V` at the keyPath `keyPath` in a receiver. As `self` is a value of type `Changeable<A>`, `self.hasChanged` will be updated to reflect whether this write actually caused a change inside of the `A`. The binary function `shouldChange` will be used to determine whether or not to write `newValue`.
///
/// - Parameters:
/// - newValue: the value to potentially write. This value will be written if `shouldChange` returns `true` when evaluated with the current value of the receiver at `keyPath`, and `newValue`, as arguments
/// - keyPath: the keyPath at which to potentially write a new value
/// - shouldChange: a binary function to determine whether `newValue` should be written. `newValue` will be written if this function returns `true` when evaluated with the current value of the receiver at `keyPath`, and `newValue`, as arguments
mutating func write<V>(
_ newValue: V,
at keyPath: WritableKeyPath<A, V>,
Expand All @@ -187,6 +200,8 @@ public extension Changeable {
Changeable.write(
newValue,
at: keyPath,
shouldChange: shouldChange))
shouldChange: shouldChange
)
)
}
}
Loading

0 comments on commit b922317

Please sign in to comment.