diff --git a/Focus.xcodeproj/project.pbxproj b/Focus.xcodeproj/project.pbxproj new file mode 100644 index 0000000..c1bdf5e --- /dev/null +++ b/Focus.xcodeproj/project.pbxproj @@ -0,0 +1,670 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 824B45F91B460AC1009AAF49 /* Focus.h in Headers */ = {isa = PBXBuildFile; fileRef = 824B45F81B460AC1009AAF49 /* Focus.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 824B46001B460AC1009AAF49 /* Focus.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 824B45F51B460AC1009AAF49 /* Focus.framework */; }; + 824B461E1B460AFA009AAF49 /* Focus.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 824B46141B460AFA009AAF49 /* Focus.framework */; }; + 824B46321B460B25009AAF49 /* Iso.swift in Sources */ = {isa = PBXBuildFile; fileRef = 824B462B1B460B25009AAF49 /* Iso.swift */; }; + 824B46331B460B25009AAF49 /* Iso.swift in Sources */ = {isa = PBXBuildFile; fileRef = 824B462B1B460B25009AAF49 /* Iso.swift */; }; + 824B46341B460B25009AAF49 /* IxCont.swift in Sources */ = {isa = PBXBuildFile; fileRef = 824B462C1B460B25009AAF49 /* IxCont.swift */; }; + 824B46351B460B25009AAF49 /* IxCont.swift in Sources */ = {isa = PBXBuildFile; fileRef = 824B462C1B460B25009AAF49 /* IxCont.swift */; }; + 824B46361B460B25009AAF49 /* IxMultiStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 824B462D1B460B25009AAF49 /* IxMultiStore.swift */; }; + 824B46371B460B25009AAF49 /* IxMultiStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 824B462D1B460B25009AAF49 /* IxMultiStore.swift */; }; + 824B46381B460B25009AAF49 /* IxState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 824B462E1B460B25009AAF49 /* IxState.swift */; }; + 824B46391B460B25009AAF49 /* IxState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 824B462E1B460B25009AAF49 /* IxState.swift */; }; + 824B463A1B460B25009AAF49 /* IxStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 824B462F1B460B25009AAF49 /* IxStore.swift */; }; + 824B463B1B460B25009AAF49 /* IxStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 824B462F1B460B25009AAF49 /* IxStore.swift */; }; + 824B463C1B460B25009AAF49 /* Lens.swift in Sources */ = {isa = PBXBuildFile; fileRef = 824B46301B460B25009AAF49 /* Lens.swift */; }; + 824B463D1B460B25009AAF49 /* Lens.swift in Sources */ = {isa = PBXBuildFile; fileRef = 824B46301B460B25009AAF49 /* Lens.swift */; }; + 824B463E1B460B25009AAF49 /* Prism.swift in Sources */ = {isa = PBXBuildFile; fileRef = 824B46311B460B25009AAF49 /* Prism.swift */; }; + 824B463F1B460B25009AAF49 /* Prism.swift in Sources */ = {isa = PBXBuildFile; fileRef = 824B46311B460B25009AAF49 /* Prism.swift */; }; + 824B46421B460BE2009AAF49 /* ArrayZipper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 824B46411B460BE2009AAF49 /* ArrayZipper.swift */; }; + 824B46431B460BE2009AAF49 /* ArrayZipper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 824B46411B460BE2009AAF49 /* ArrayZipper.swift */; }; + 824B46481B460C1E009AAF49 /* LensOperators.swift in Sources */ = {isa = PBXBuildFile; fileRef = 824B46471B460C1E009AAF49 /* LensOperators.swift */; }; + 824B46491B460C1E009AAF49 /* LensOperators.swift in Sources */ = {isa = PBXBuildFile; fileRef = 824B46471B460C1E009AAF49 /* LensOperators.swift */; }; + 824B464C1B460E69009AAF49 /* PartyExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 824B464A1B460E69009AAF49 /* PartyExample.swift */; }; + 824B464D1B460E69009AAF49 /* PartyExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 824B464A1B460E69009AAF49 /* PartyExample.swift */; }; + 824B464E1B460E69009AAF49 /* UserExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 824B464B1B460E69009AAF49 /* UserExample.swift */; }; + 824B464F1B460E69009AAF49 /* UserExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 824B464B1B460E69009AAF49 /* UserExample.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 824B46011B460AC1009AAF49 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 824B45EC1B460AC1009AAF49 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 824B45F41B460AC1009AAF49; + remoteInfo = Focus; + }; + 824B461F1B460AFA009AAF49 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 824B45EC1B460AC1009AAF49 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 824B46131B460AFA009AAF49; + remoteInfo = "Focus-iOS"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 824B45F51B460AC1009AAF49 /* Focus.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Focus.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 824B45F81B460AC1009AAF49 /* Focus.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Focus.h; path = Focus/Focus.h; sourceTree = ""; }; + 824B45FA1B460AC1009AAF49 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 824B45FF1B460AC1009AAF49 /* FocusTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FocusTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 824B46061B460AC1009AAF49 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 824B46141B460AFA009AAF49 /* Focus.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Focus.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 824B461D1B460AFA009AAF49 /* Focus-iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Focus-iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 824B462B1B460B25009AAF49 /* Iso.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Iso.swift; sourceTree = ""; }; + 824B462C1B460B25009AAF49 /* IxCont.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IxCont.swift; sourceTree = ""; }; + 824B462D1B460B25009AAF49 /* IxMultiStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IxMultiStore.swift; sourceTree = ""; }; + 824B462E1B460B25009AAF49 /* IxState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IxState.swift; sourceTree = ""; }; + 824B462F1B460B25009AAF49 /* IxStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IxStore.swift; sourceTree = ""; }; + 824B46301B460B25009AAF49 /* Lens.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Lens.swift; sourceTree = ""; }; + 824B46311B460B25009AAF49 /* Prism.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Prism.swift; sourceTree = ""; }; + 824B46411B460BE2009AAF49 /* ArrayZipper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayZipper.swift; sourceTree = ""; }; + 824B46471B460C1E009AAF49 /* LensOperators.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LensOperators.swift; sourceTree = ""; }; + 824B464A1B460E69009AAF49 /* PartyExample.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PartyExample.swift; sourceTree = ""; }; + 824B464B1B460E69009AAF49 /* UserExample.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserExample.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 824B45F11B460AC1009AAF49 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 824B45FC1B460AC1009AAF49 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 824B46001B460AC1009AAF49 /* Focus.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 824B46101B460AFA009AAF49 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 824B461A1B460AFA009AAF49 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 824B461E1B460AFA009AAF49 /* Focus.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 824B45EB1B460AC1009AAF49 = { + isa = PBXGroup; + children = ( + 824B45F81B460AC1009AAF49 /* Focus.h */, + 824B45F71B460AC1009AAF49 /* Focus */, + 824B46031B460AC1009AAF49 /* FocusTests */, + 824B45F61B460AC1009AAF49 /* Products */, + ); + sourceTree = ""; + }; + 824B45F61B460AC1009AAF49 /* Products */ = { + isa = PBXGroup; + children = ( + 824B45F51B460AC1009AAF49 /* Focus.framework */, + 824B45FF1B460AC1009AAF49 /* FocusTests.xctest */, + 824B46141B460AFA009AAF49 /* Focus.framework */, + 824B461D1B460AFA009AAF49 /* Focus-iOSTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 824B45F71B460AC1009AAF49 /* Focus */ = { + isa = PBXGroup; + children = ( + 824B46411B460BE2009AAF49 /* ArrayZipper.swift */, + 824B46471B460C1E009AAF49 /* LensOperators.swift */, + 824B46301B460B25009AAF49 /* Lens.swift */, + 824B462B1B460B25009AAF49 /* Iso.swift */, + 824B46311B460B25009AAF49 /* Prism.swift */, + 824B462C1B460B25009AAF49 /* IxCont.swift */, + 824B462D1B460B25009AAF49 /* IxMultiStore.swift */, + 824B462E1B460B25009AAF49 /* IxState.swift */, + 824B462F1B460B25009AAF49 /* IxStore.swift */, + 824B46401B460B28009AAF49 /* Supporting Files */, + ); + path = Focus; + sourceTree = ""; + }; + 824B46031B460AC1009AAF49 /* FocusTests */ = { + isa = PBXGroup; + children = ( + 824B464A1B460E69009AAF49 /* PartyExample.swift */, + 824B464B1B460E69009AAF49 /* UserExample.swift */, + 824B46061B460AC1009AAF49 /* Info.plist */, + ); + path = FocusTests; + sourceTree = ""; + }; + 824B46401B460B28009AAF49 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 824B45FA1B460AC1009AAF49 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 824B45F21B460AC1009AAF49 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 824B45F91B460AC1009AAF49 /* Focus.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 824B46111B460AFA009AAF49 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 824B45F41B460AC1009AAF49 /* Focus */ = { + isa = PBXNativeTarget; + buildConfigurationList = 824B46091B460AC1009AAF49 /* Build configuration list for PBXNativeTarget "Focus" */; + buildPhases = ( + 824B45F01B460AC1009AAF49 /* Sources */, + 824B45F11B460AC1009AAF49 /* Frameworks */, + 824B45F21B460AC1009AAF49 /* Headers */, + 824B45F31B460AC1009AAF49 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Focus; + productName = Focus; + productReference = 824B45F51B460AC1009AAF49 /* Focus.framework */; + productType = "com.apple.product-type.framework"; + }; + 824B45FE1B460AC1009AAF49 /* FocusTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 824B460C1B460AC1009AAF49 /* Build configuration list for PBXNativeTarget "FocusTests" */; + buildPhases = ( + 824B45FB1B460AC1009AAF49 /* Sources */, + 824B45FC1B460AC1009AAF49 /* Frameworks */, + 824B45FD1B460AC1009AAF49 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 824B46021B460AC1009AAF49 /* PBXTargetDependency */, + ); + name = FocusTests; + productName = FocusTests; + productReference = 824B45FF1B460AC1009AAF49 /* FocusTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 824B46131B460AFA009AAF49 /* Focus-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 824B46291B460AFA009AAF49 /* Build configuration list for PBXNativeTarget "Focus-iOS" */; + buildPhases = ( + 824B460F1B460AFA009AAF49 /* Sources */, + 824B46101B460AFA009AAF49 /* Frameworks */, + 824B46111B460AFA009AAF49 /* Headers */, + 824B46121B460AFA009AAF49 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Focus-iOS"; + productName = "Focus-iOS"; + productReference = 824B46141B460AFA009AAF49 /* Focus.framework */; + productType = "com.apple.product-type.framework"; + }; + 824B461C1B460AFA009AAF49 /* Focus-iOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 824B462A1B460AFA009AAF49 /* Build configuration list for PBXNativeTarget "Focus-iOSTests" */; + buildPhases = ( + 824B46191B460AFA009AAF49 /* Sources */, + 824B461A1B460AFA009AAF49 /* Frameworks */, + 824B461B1B460AFA009AAF49 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 824B46201B460AFA009AAF49 /* PBXTargetDependency */, + ); + name = "Focus-iOSTests"; + productName = "Focus-iOSTests"; + productReference = 824B461D1B460AFA009AAF49 /* Focus-iOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 824B45EC1B460AC1009AAF49 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0700; + LastUpgradeCheck = 0700; + ORGANIZATIONNAME = TypeLift; + TargetAttributes = { + 824B45F41B460AC1009AAF49 = { + CreatedOnToolsVersion = 7.0; + }; + 824B45FE1B460AC1009AAF49 = { + CreatedOnToolsVersion = 7.0; + }; + 824B46131B460AFA009AAF49 = { + CreatedOnToolsVersion = 7.0; + }; + 824B461C1B460AFA009AAF49 = { + CreatedOnToolsVersion = 7.0; + }; + }; + }; + buildConfigurationList = 824B45EF1B460AC1009AAF49 /* Build configuration list for PBXProject "Focus" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 824B45EB1B460AC1009AAF49; + productRefGroup = 824B45F61B460AC1009AAF49 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 824B45F41B460AC1009AAF49 /* Focus */, + 824B45FE1B460AC1009AAF49 /* FocusTests */, + 824B46131B460AFA009AAF49 /* Focus-iOS */, + 824B461C1B460AFA009AAF49 /* Focus-iOSTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 824B45F31B460AC1009AAF49 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 824B45FD1B460AC1009AAF49 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 824B46121B460AFA009AAF49 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 824B461B1B460AFA009AAF49 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 824B45F01B460AC1009AAF49 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 824B46361B460B25009AAF49 /* IxMultiStore.swift in Sources */, + 824B463E1B460B25009AAF49 /* Prism.swift in Sources */, + 824B46341B460B25009AAF49 /* IxCont.swift in Sources */, + 824B46381B460B25009AAF49 /* IxState.swift in Sources */, + 824B46321B460B25009AAF49 /* Iso.swift in Sources */, + 824B46421B460BE2009AAF49 /* ArrayZipper.swift in Sources */, + 824B463A1B460B25009AAF49 /* IxStore.swift in Sources */, + 824B46481B460C1E009AAF49 /* LensOperators.swift in Sources */, + 824B463C1B460B25009AAF49 /* Lens.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 824B45FB1B460AC1009AAF49 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 824B464C1B460E69009AAF49 /* PartyExample.swift in Sources */, + 824B464E1B460E69009AAF49 /* UserExample.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 824B460F1B460AFA009AAF49 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 824B46371B460B25009AAF49 /* IxMultiStore.swift in Sources */, + 824B463F1B460B25009AAF49 /* Prism.swift in Sources */, + 824B46351B460B25009AAF49 /* IxCont.swift in Sources */, + 824B46391B460B25009AAF49 /* IxState.swift in Sources */, + 824B46331B460B25009AAF49 /* Iso.swift in Sources */, + 824B46431B460BE2009AAF49 /* ArrayZipper.swift in Sources */, + 824B463B1B460B25009AAF49 /* IxStore.swift in Sources */, + 824B46491B460C1E009AAF49 /* LensOperators.swift in Sources */, + 824B463D1B460B25009AAF49 /* Lens.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 824B46191B460AFA009AAF49 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 824B464D1B460E69009AAF49 /* PartyExample.swift in Sources */, + 824B464F1B460E69009AAF49 /* UserExample.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 824B46021B460AC1009AAF49 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 824B45F41B460AC1009AAF49 /* Focus */; + targetProxy = 824B46011B460AC1009AAF49 /* PBXContainerItemProxy */; + }; + 824B46201B460AFA009AAF49 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 824B46131B460AFA009AAF49 /* Focus-iOS */; + targetProxy = 824B461F1B460AFA009AAF49 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 824B46071B460AC1009AAF49 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 824B46081B460AC1009AAF49 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.10; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 824B460A1B460AC1009AAF49 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = Focus/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.TypeLift.Focus; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 824B460B1B460AC1009AAF49 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = Focus/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.TypeLift.Focus; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 824B460D1B460AC1009AAF49 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = FocusTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.TypeLift.FocusTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 824B460E1B460AC1009AAF49 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = FocusTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.TypeLift.FocusTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 824B46251B460AFA009AAF49 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = Focus/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.TypeLift.Focus-iOS"; + PRODUCT_NAME = Focus; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 824B46261B460AFA009AAF49 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = Focus/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.TypeLift.Focus-iOS"; + PRODUCT_NAME = Focus; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 824B46271B460AFA009AAF49 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + INFOPLIST_FILE = FocusTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.TypeLift.Focus-iOSTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 824B46281B460AFA009AAF49 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + INFOPLIST_FILE = FocusTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.TypeLift.Focus-iOSTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 824B45EF1B460AC1009AAF49 /* Build configuration list for PBXProject "Focus" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 824B46071B460AC1009AAF49 /* Debug */, + 824B46081B460AC1009AAF49 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 824B46091B460AC1009AAF49 /* Build configuration list for PBXNativeTarget "Focus" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 824B460A1B460AC1009AAF49 /* Debug */, + 824B460B1B460AC1009AAF49 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 824B460C1B460AC1009AAF49 /* Build configuration list for PBXNativeTarget "FocusTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 824B460D1B460AC1009AAF49 /* Debug */, + 824B460E1B460AC1009AAF49 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 824B46291B460AFA009AAF49 /* Build configuration list for PBXNativeTarget "Focus-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 824B46251B460AFA009AAF49 /* Debug */, + 824B46261B460AFA009AAF49 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 824B462A1B460AFA009AAF49 /* Build configuration list for PBXNativeTarget "Focus-iOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 824B46271B460AFA009AAF49 /* Debug */, + 824B46281B460AFA009AAF49 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 824B45EC1B460AC1009AAF49 /* Project object */; +} diff --git a/Focus.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Focus.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..50f4d2c --- /dev/null +++ b/Focus.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Focus/ArrayZipper.swift b/Focus/ArrayZipper.swift new file mode 100644 index 0000000..3d537fa --- /dev/null +++ b/Focus/ArrayZipper.swift @@ -0,0 +1,89 @@ +// +// ArrayZipper.swift +// swiftz +// +// Created by Alexander Ronald Altman on 8/4/14. +// Copyright (c) 2014 Maxwell Swadling. All rights reserved. +// + +/// A zipper for arrays. Zippers are convenient ways of traversing and modifying the parts of a +/// structure using a cursor to focus on its individual parts. +public struct ArrayZipper : ArrayLiteralConvertible { + typealias Element = A + + /// The underlying array of values. + public let values : [A] + /// The position of the cursor within the Array. + public let position : Int + + public init(_ values : [A] = [], _ position : Int = 0) { + if position < 0 { + self.position = 0 + } else if position >= values.count { + self.position = values.count - 1 + } else { + self.position = position + } + self.values = values + } + + /// Creates an ArrayZipper pointing at the head of a given list of elements. + public init(arrayLiteral elements : Element...) { + self.init(elements, 0) + } + + /// Creates an `ArrayZipper` with the cursor adjusted by n in the direction of the sign of the + /// given value. + public func move(n : Int = 1) -> ArrayZipper { + return ArrayZipper(values, position + n) + } + + /// Creates an `ArrayZipper` with the cursor set to a given position value. + public func moveTo(pos : Int) -> ArrayZipper { + return ArrayZipper(values, pos) + } + + /// Returns whether the cursor of the receiver is at the end of its underlying Array. + public var isAtEnd : Bool { + return position >= (values.count - 1) + } +} + +extension ArrayZipper /*: Functor*/ { + typealias B = Any + typealias FB = ArrayZipper + + public func fmap(f : A -> B) -> ArrayZipper { + return ArrayZipper(self.values.map(f), self.position) + } +} + +public func <^> (f : A -> B, xz : ArrayZipper) -> ArrayZipper { + return xz.fmap(f) +} + +extension ArrayZipper /*: Copointed*/ { + /// Extracts the value at the position of the receiver's cursor. + /// + /// This function is not total, but makes the guarantee that if `zipper.isAtEnd` returns false, + /// it is safe to call. + public func extract() -> A { + return self.values[self.position] + } +} + +extension ArrayZipper /*: Comonad*/ { + typealias FFA = ArrayZipper> + + public func duplicate() -> ArrayZipper> { + return ArrayZipper>((0 ..< self.values.count).map { ArrayZipper(self.values, $0) }, self.position) + } + + public func extend(f : ArrayZipper -> B) -> ArrayZipper { + return ArrayZipper((0 ..< self.values.count).map { f(ArrayZipper(self.values, $0)) }, self.position) + } +} + +public func ->> (xz : ArrayZipper, f: ArrayZipper -> B) -> ArrayZipper { + return xz.extend(f) +} diff --git a/Focus/Focus.h b/Focus/Focus.h new file mode 100644 index 0000000..22a0439 --- /dev/null +++ b/Focus/Focus.h @@ -0,0 +1,19 @@ +// +// Focus.h +// Focus +// +// Created by Robert Widmann on 7/2/15. +// Copyright © 2015 TypeLift. All rights reserved. +// + +#import + +//! Project version number for Focus. +FOUNDATION_EXPORT double FocusVersionNumber; + +//! Project version string for Focus. +FOUNDATION_EXPORT const unsigned char FocusVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + diff --git a/Focus/Info.plist b/Focus/Info.plist new file mode 100644 index 0000000..8d41819 --- /dev/null +++ b/Focus/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSHumanReadableCopyright + Copyright © 2015 TypeLift. All rights reserved. + NSPrincipalClass + + + diff --git a/Focus/Iso.swift b/Focus/Iso.swift new file mode 100644 index 0000000..4c534bb --- /dev/null +++ b/Focus/Iso.swift @@ -0,0 +1,54 @@ +// +// Iso.swift +// swiftz +// +// Created by Alexander Ronald Altman on 7/22/14. +// Copyright (c) 2015 TypeLift. All rights reserved. +// + +/// Captures an isomorphism between S and A. +/// +/// :param: S The source of the Iso heading right +/// :param: T The target of the Iso heading left +/// :param: A The source of the Iso heading right +/// :param: B The target of the Iso heading left +public struct Iso { + public let get : S -> A + public let inject : B -> T + + /// Builds an Iso from a pair of inverse functions. + public init(get : S -> A, inject : B -> T) { + self.get = get + self.inject = inject + } + + /// Runs a value of type `S` along both parts of the Iso. + public func modify(v : S, _ f : A -> B) -> T { + return inject(f(get(v))) + } + + /// Composes an `Iso` with the receiver. + public func compose(i2 : Iso) -> Iso { + return self • i2 + } + + /// Converts an Iso to a Lens. + public var asLens : Lens { + return Lens { s in IxStore(self.get(s)) { self.inject($0) } } + } + + /// Converts an Iso to a Prism with a getter that always succeeds.. + public var asPrism : Prism { + return Prism(tryGet: { .Some(self.get($0)) }, inject: inject) + } +} + +/// The identity isomorphism. +public func identity() -> Iso { + return Iso(get: identity, inject: identity) +} + +/// Compose isomorphisms. +public func • (i1 : Iso, i2 : Iso) -> Iso { + return Iso(get: i2.get • i1.get, inject: i1.inject • i2.inject) +} diff --git a/Focus/IxCont.swift b/Focus/IxCont.swift new file mode 100644 index 0000000..39ba0c4 --- /dev/null +++ b/Focus/IxCont.swift @@ -0,0 +1,89 @@ +// +// IxCont.swift +// swiftz +// +// Created by Alexander Ronald Altman on 6/10/14. +// Copyright (c) 2015 TypeLift. All rights reserved. +// + +/// `IxCont` is the Continuation Monad indexed by a result type `R`, an immediate output type `O` +/// and a value `A`. +public struct IxCont { + /// Lowers an `IxCont` to an indexed continuation function. + public let run : (A -> O) -> R + + /// Lifts an indexed continuation function into an `IxCont`. + public init(_ run : (A -> O) -> R) { + self.run = run + } + + /// Applies a function that transforms the input value of the continuation function. + public func map(f : A -> B) -> IxCont { + return f <^> self + } + + /// Applies a function that transforms the final output value of the continuation function. + public func imap(f : R -> S) -> IxCont { + return f <^^> self + } + + /// Applies a function that transforms the immediate output value of the continuation function. + public func contramap(f : N -> O) -> IxCont { + return f self + } + + /// Composes two continuation functions by applying the final result of the second to the + /// immediate value of the first then running both continuations in series. + public func ap(f : IxCont B>) -> IxCont { + return f <*> self + } + + /// Fits the receiver together with a second continuation and runs them in series. + public func flatMap(f : A -> IxCont) -> IxCont { + return self >>- f + } +} + +public func run(a : IxCont) -> R { + return a.run(identity) +} + +public func pure(x : A) -> IxCont { + return IxCont { $0(x) } +} + +public func <^> (f : A -> B, a: IxCont) -> IxCont { + return IxCont { k in a.run { k(f($0)) } } +} + +public func <^^> (f : R -> S, a: IxCont) -> IxCont { + return IxCont { f(a.run($0)) } +} + +public func (f : N -> O, a: IxCont) -> IxCont { + return IxCont { k in a.run { f(k($0)) } } +} + +public func <*> (f : IxCont B>, a: IxCont) -> IxCont { + return IxCont { k in f.run { g in a.run { k(g($0)) } } } +} + +public func >>- (a : IxCont, f: A -> IxCont) -> IxCont { + return IxCont { k in a.run { f($0).run(k) } } +} + +public func join(a : IxCont>) -> IxCont { + return IxCont { k in a.run { $0.run(k) } } +} + +public func shift(f : (A -> IxCont) -> IxCont) -> IxCont { + return IxCont { k in run(f { pure(k($0)) }) } +} + +public func reset(a : IxCont) -> IxCont { + return pure(run(a)) +} + +public func callCC(f : (A -> IxCont) -> IxCont) -> IxCont { + return IxCont { k in (f { x in IxCont { _ in k(x) } }).run(k) } +} diff --git a/Focus/IxMultiStore.swift b/Focus/IxMultiStore.swift new file mode 100644 index 0000000..e1cc4e7 --- /dev/null +++ b/Focus/IxMultiStore.swift @@ -0,0 +1,104 @@ +// +// IxMultiStore.swift +// swiftz +// +// Created by Alexander Ronald Altman on 8/4/14. +// Copyright (c) 2015 TypeLift. All rights reserved. +// + +/// The Store Comonad Transformer indexed by a position type `O` and the ArrayZipper Comonad. +public struct IxMultiStore { + /// The current position of the receiver. + let pos : O + + /// Retrieves a zipper that focuses on functions that retrieve values at index I. + let set : ArrayZipper A> + + public init(_ pos: O, _ set: ArrayZipper A>) { + self.pos = pos + self.set = set + } + + /// Applies a function to the retrieval of values. + public func map(f : A -> B) -> IxMultiStore { + return f <^> self + } + + /// Applies a function to the position indexes that can be focused on by the underlying zipper. + public func imap

(f : O -> P) -> IxMultiStore { + return f <^^> self + } + + /// Applies a function to the retrieval indexes of the underlying zipper. + public func contramap(f : H -> I) -> IxMultiStore { + return f self + } + + /// Returns an `IxStore` that retrieves an `IxStore` for every index in the receiver. + public func duplicate() -> IxMultiStore> { + return IxMultiStore>(pos, set ->> { g in { IxMultiStore($0, g) } }) + } + + /// Extends the context of the store with a function that retrieves values from another store + /// indexed by a different position. + public func extend(f : IxMultiStore -> B) -> IxMultiStore { + return self ->> f + } + + /// Extracts a zipper that focuses on all values at a given index. + public func put(x : I) -> ArrayZipper { + return { $0(x) } <^> set + } + + /// Extracts a zipper that focuses on all values at an index given by applying a function to the + /// receiver's position index. + public func puts(f : O -> I) -> ArrayZipper { + return put(f(pos)) + } + + /// Extracts the first focused value from the store at a given index. + public func peek(x : I) -> A { + return put(x).extract() + } + + /// Extracts the first focused value from the store at an index given by applying a function to + /// the receiver's position index. + public func peeks(f : O -> I) -> A { + return peek(f(pos)) + } + + /// Returns a new `IxMultiStore` with its position index set to the given value. + public func seek

(x : P) -> IxMultiStore { + return IxMultiStore(x, set) + } + + /// Returns a new `IxMultiStore` with its position index set to the result of applying the given + /// function to the current position index. + public func seeks

(f : O -> P) -> IxMultiStore { + return IxMultiStore(f(pos), set) + } +} + +public func extract(a : IxMultiStore) -> A { + return a.set.extract()(a.pos) +} + +public func <^> (f : A -> B, a : IxMultiStore) -> IxMultiStore { + return IxMultiStore(a.pos, { g in { f(g($0)) } } <^> a.set) +} + +public func<^^>(f : O -> P, a : IxMultiStore) -> IxMultiStore { + return IxMultiStore(f(a.pos), a.set) +} + +public func (f : H -> I, a : IxMultiStore) -> IxMultiStore { + return IxMultiStore(a.pos, { $0 • f } <^> a.set) +} + +public func ->> (a : IxMultiStore, f : IxMultiStore -> B) -> IxMultiStore { + return IxMultiStore(a.pos, a.set ->> { g in { f(IxMultiStore($0, g)) } }) +} + +public func lower(a : IxMultiStore) -> ArrayZipper { + return { $0(a.pos) } <^> a.set +} diff --git a/Focus/IxState.swift b/Focus/IxState.swift new file mode 100644 index 0000000..3c8f8bc --- /dev/null +++ b/Focus/IxState.swift @@ -0,0 +1,119 @@ +// +// IxState.swift +// swiftz +// +// Created by Alexander Ronald Altman on 6/11/14. +// Copyright (c) 2015 TypeLift. All rights reserved. +// + +/// IxState is a State Monad that carries extra type-level state (`I`) through its computation. +public struct IxState { + /// Extracts a final value and state given an index. + let run : I -> (A, O) + + /// Lifts an indexed state computation into an `IxState`. + public init(_ run : I -> (A, O)) { + self.run = run + } + + /// Evaluates the receiver's underlying state computation with the given index and returns the + /// final value, discarding the final state. + public func eval(s : I) -> A { + return run(s).0 + } + + /// Evaluates the receiver's underlying state computation with the given index and returns the + /// final state, discarding the final value. + public func exec(s : I) -> O { + return run(s).1 + } + + /// Applies a function to the final value generated by the receiver's underlying state + /// computation. + public func map(f : A -> B) -> IxState { + return f <^> self + } + + /// Uses the function to witness a new `IxState` indexed by a different type. + public func contramap(f : H -> I) -> IxState { + return f self + } + + /// Applies a function to the final state value generated by the receivers underlying state + /// computation. + public func imap

(f : O -> P) -> IxState { + return f <^^> self + } + + /// Runs both stateful computations, applying the resulting function to the final value of the + /// receiver. + public func ap(f : IxState B>) -> IxState { + return f <*> self + } + + /// Uses the final value of the receiver to produce another stateful computation. + public func flatMap(f : A -> IxState) -> IxState { + return self >>- f + } + +} + +public func pure(x : A) -> IxState { + return IxState { (x, $0) } +} + +public func <^> (f : A -> B, a : IxState) -> IxState { + return IxState { s1 in + let (x, s2) = a.run(s1) + return (f(x), s2) + } +} + +public func (f : H -> I, a : IxState) -> IxState { + return IxState { a.run(f($0)) } +} + +public func <^^> (f : O -> P, a : IxState) -> IxState { + return IxState { s1 in + let (x, s2) = a.run(s1) + return (x, f(s2)) + } +} + +public func <*> (f : IxState B>, a : IxState) -> IxState { + return IxState { s1 in + let (g, s2) = f.run(s1) + let (x, s3) = a.run(s2) + return (g(x), s3) + } +} + +public func >>- (a : IxState, f : A -> IxState) -> IxState { + return IxState { s1 in + let (x, s2) = a.run(s1) + return f(x).run(s2) + } +} + +public func join(a : IxState>) -> IxState { + return IxState { s1 in + let (b, s2) = a.run(s1) + return b.run(s2) + } +} + +public func get() -> IxState { + return IxState { ($0, $0) } +} + +public func gets(f : I -> A) -> IxState { + return IxState { (f($0), $0) } +} + +public func put(s : O) -> IxState { + return IxState { _ in ((), s) } +} + +public func modify(f : I -> O) -> IxState { + return IxState { ((), f($0)) } +} diff --git a/Focus/IxStore.swift b/Focus/IxStore.swift new file mode 100644 index 0000000..0e72d78 --- /dev/null +++ b/Focus/IxStore.swift @@ -0,0 +1,117 @@ +// +// IxStore.swift +// swiftz +// +// Created by Alexander Ronald Altman on 6/12/14. +// Copyright (c) 2015 TypeLift. All rights reserved. +// + +/// An `IxStore` models a store of variables of type `A` each at an index of type `I`. Unlike the +/// Costate Comonad, `IxStore`'s position is indexed by a type `O`. +/// +/// N.B.: In the indexed store comonad transformer, set, put, and peek are all distinct, +/// as are puts and peeks. The lack of distinction here is due to the lack of transformer +/// nature; as soon as we get transformers, that will change. +public struct IxStore { + /// The current position of the receiver. + let pos : O + + /// Retrieves the value at index `I`. + let set : I -> A + + public init(_ pos: O, _ set: I -> A) { + self.pos = pos + self.set = set + } + + /// Applies a function to the retrieval of values. + public func map(f : A -> B) -> IxStore { + return f <^> self + } + + /// Applies a function to the position index. + public func imap

(f : O -> P) -> IxStore { + return f <^^> self + } + + /// Applies a function to the retrieval index. + public func contramap(f : H -> I) -> IxStore { + return f self + } + + /// Returns an `IxStore` that retrieves an `IxStore` for every index in the receiver. + public func duplicate() -> IxStore> { + return IxStore>(pos) { IxStore($0, self.set) } + } + + /// Extends the context of the store with a function that retrieves values from another store + /// indexed by a different position. + public func extend(f : IxStore -> B) -> IxStore { + return self ->> f + } + + /// Extracts a value from the store at a given index. + public func peek(x : I) -> A { + return set(x) + } + + /// Extracts a value from the store at an index given by applying a function to the receiver's + /// position index. + public func peeks(f : O -> I) -> A { + return set(f(pos)) + } + + /// Extracts a value from the store at a given index. + /// + /// With a proper Monad Transformer this function would use a Comonadic context to extract a + /// value. + public func put(x : I) -> A { + return set(x) + } + + /// Extracts a value from the store at an index given by applying a function to the receiver's + /// position index. + /// + /// With a proper Monad Transformer this function would use a Comonadic context to extract a + /// value. + public func puts(f : O -> I) -> A { + return set(f(pos)) + } + + /// Returns a new `IxStore` with its position index set to the given value. + public func seek

(x : P) -> IxStore { + return IxStore(x, set) + } + + /// Returns a new `IxStore` with its position index set to the result of applying the given + /// function to the current position index. + public func seeks

(f : O -> P) -> IxStore { + return IxStore(f(pos), set) + } +} + +/// The trivial `IxStore` always retrieves the same value at all indexes. +public func trivial(x : A) -> IxStore { + return IxStore(x, identity) +} + +/// Extracts a value from the receiver at its position index. +public func extract(a : IxStore) -> A { + return a.set(a.pos) +} + +public func <^> (f : A -> B, a : IxStore) -> IxStore { + return IxStore(a.pos) { f(a.set($0)) } +} + +public func <^^> (f : O -> P, a : IxStore) -> IxStore { + return IxStore(f(a.pos), a.set) +} + +public func (f : H -> I, a : IxStore) -> IxStore { + return IxStore(a.pos) { a.set(f($0)) } +} + +public func ->> (a : IxStore, f : IxStore -> B) -> IxStore { + return IxStore(a.pos) { f(IxStore($0, a.set)) } +} diff --git a/Focus/Lens.swift b/Focus/Lens.swift new file mode 100644 index 0000000..12dfa14 --- /dev/null +++ b/Focus/Lens.swift @@ -0,0 +1,105 @@ +// +// Lens.swift +// swiftz +// +// Created by Maxwell Swadling on 8/06/2014. +// Copyright (c) 2015 TypeLift. All rights reserved. +// + +/// A Lens (or Functional Reference) describes a way of focusing on the parts of a structure, +/// composing with other lenses to focus deeper into a structure, and returning new structures with +/// parts modified. In this way, a Lens can be thought of as a reference to a subpart of a +/// structure. +/// +/// A well-behaved Lens should obey the following laws: +/// +/// - You get back what you put in: +/// +/// l.get(l.set(s, b)) == b +/// +/// - Putting back what you got doesn't change anything: +/// +/// l.set(s, l.get(a)) == a +/// +/// - Setting twice is the same as setting once: +/// +/// l.set(l.set(s, a), b) == l.set(s, b) +/// +/// :param: S The source of the Lens +/// :param: T The modified source of the Lens +/// :param: A The target of the Lens +/// :param: B The modified target the Lens +public struct Lens { + /// Gets the Indexed Costate Comonad Coalgebroid underlying the receiver. + public let run : S -> IxStore + + public init(_ run : S -> IxStore) { + self.run = run + } + + /// Creates a lens from a getter/setter pair. + public init(get : S -> A, set : (S, B) -> T) { + self.init({ v in IxStore(get(v)) { set(v, $0) } }) + } + + /// Creates a lens that transforms set values by a given function before they are returned. + public init(get : S -> A, modify : (S, A -> B) -> T) { + self.init(get: get, set: { v, x in modify(v) { _ in x } }) + } + + /// Composes a `Lens` with the receiver. + public func compose(l2 : Lens) -> Lens { + return self • l2 + } + + /// Runs the getter on a given structure. + public func get(v : S) -> A { + return run(v).pos + } + + /// Runs the setter on a given structure and value to yield a new structure. + public func set(v : S, _ x : B) -> T { + return run(v).peek(x) + } + + /// Transform the value of the retrieved field by a function. + public func modify(v : S, _ f : A -> B) -> T { + let q = run(v) + return q.peek(f(q.pos)) + } + + /// Uses the receiver to focus in on a State Monad. + public func zoom(a : IxState) -> IxState { + return IxState { s1 in + let q = self.run(s1) + let (x, s2) = a.run(q.pos) + return (x, q.peek(s2)) + } + } + + /// Creates a Lens that focuses on two structures. + public func split(right : Lens) -> Lens<(S, S_), (T, T_), (A, A_), (B, B_)> { + return Lens<(S, S_), (T, T_), (A, A_), (B, B_)> { (vl, vr) in + let q1 = self.run(vl) + let q2 = right.run(vr) + return IxStore((q1.pos, q2.pos)) { (l, r) in (q1.peek(l), q2.peek(r)) } + } + } + + /// Creates a Lens that sends its input structure to both Lenses to focus on distinct subparts. + public func fanout(right : Lens) -> Lens { + return Lens { s in + let q1 = self.run(s) + let q2 = right.run(s) + return IxStore((q1.pos, q2.pos)) { (q1.peek($0), q2.peek($0)) } + } + } +} + +public func • (l1 : Lens, l2 : Lens) -> Lens { + return Lens { v in + let q1 = l1.run(v) + let q2 = l2.run(q1.pos) + return IxStore(q2.pos) { q1.peek(q2.peek($0)) } + } +} diff --git a/Focus/LensOperators.swift b/Focus/LensOperators.swift new file mode 100644 index 0000000..89768de --- /dev/null +++ b/Focus/LensOperators.swift @@ -0,0 +1,69 @@ +// +// Operator.swift +// Focus +// +// Created by Robert Widmann on 7/2/15. +// Copyright © 2015 TypeLift. All rights reserved. +// + +/// Compose | Applies one function to the result of another function to produce a third function. +infix operator • { + associativity right + precedence 190 +} + +/// MARK: Control.* + +/// Fmap | Maps a function over the value encapsulated by a functor. +infix operator <^> { + associativity left + precedence 140 +} + +/// Imap | Maps covariantly over the index of a right-leaning bifunctor. +infix operator <^^> { + associativity left + precedence 140 +} + +/// Contramap | Contravariantly maps a function over the value encapsulated by a functor. +infix operator { + associativity left + precedence 140 +} + +/// Ap | Applies a function encapsulated by a functor to the value encapsulated by another functor. +infix operator <*> { + associativity left + precedence 140 +} + +/// Bind | Sequences and composes two monadic actions by passing the value inside the monad on the +/// left to a function on the right yielding a new monad. +infix operator >>- { + associativity left + precedence 110 +} + +/// Extend | Duplicates the surrounding context and computes a value from it while remaining in the +/// original context. +infix operator ->> { + associativity left + precedence 110 +} + +/// The identity function. +internal func identity(a : A) -> A { + return a +} + +/// Compose | Applies one function to the result of another function to produce a third function. +/// +/// f : B -> C +/// g : A -> B +/// (f • g)(x) === f(g(x)) : A -> B -> C +internal func • (f : B -> C, g: A -> B) -> A -> C { + return { (a : A) -> C in + return f(g(a)) + } +} diff --git a/Focus/Prism.swift b/Focus/Prism.swift new file mode 100644 index 0000000..692a766 --- /dev/null +++ b/Focus/Prism.swift @@ -0,0 +1,49 @@ +// +// Prism.swift +// swiftz +// +// Created by Alexander Ronald Altman on 7/22/14. +// Copyright (c) 2015 TypeLift. All rights reserved. +// + +/// A Prism is an `Iso` where one of the functions is partial. +/// +/// :param: S The source of the Prism +/// :param: T The modified source of the Prism +/// :param: A The possible target of the Prism +/// :param: B The modified target the Prism +public struct Prism { + public let tryGet : S -> A? + public let inject : B -> T + + public init(tryGet : S -> A?, inject : B -> T) { + self.tryGet = tryGet + self.inject = inject + } + + /// Composes a `Prism` with the receiver. + public func compose(i2 : Prism) -> Prism { + return self • i2 + } + + /// Attempts to run a value of type `S` along both parts of the Prism. If `.None` is + /// encountered along the getter returns `.None`, else returns `.Some` containing the final + /// value. + public func tryModify(s : S, _ f : A -> B) -> T? { + return tryGet(s).map(self.inject • f) + } +} + +public func • (p1 : Prism, p2 : Prism) -> Prism { + return Prism(tryGet: { p1.tryGet($0).flatMap(p2.tryGet) }, inject: p1.inject • p2.inject) +} + +/// Provides a Prism for tweaking values inside `.Some`. +public func _Some() -> Prism { + return Prism(tryGet: identity, inject: Optional.Some) +} + +/// Provides a Prism for traversing `.None`. +public func _None() -> Prism { + return Prism(tryGet: { _ in .None }, inject: { _ in .None }) +} diff --git a/FocusTests/Info.plist b/FocusTests/Info.plist new file mode 100644 index 0000000..ba72822 --- /dev/null +++ b/FocusTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/FocusTests/PartyExample.swift b/FocusTests/PartyExample.swift new file mode 100644 index 0000000..5a17c55 --- /dev/null +++ b/FocusTests/PartyExample.swift @@ -0,0 +1,44 @@ +// +// PartyExample.swift +// swiftz +// +// Created by Maxwell Swadling on 9/06/2014. +// Copyright (c) 2014 Maxwell Swadling. All rights reserved. +// + +import XCTest +import Focus + +// A party has a host, who is a user. +// A lens example +class Party { + let host : User + + init(h : User) { + host = h + } + + class func lpartyHost() -> Lens { + let getter = { (party : Party) -> User in + party.host + } + + let setter = { (party : Party, host : User) -> Party in + Party(h: host) + } + + return Lens(get: getter, set: setter) + } +} + +class PartySpec : XCTestCase { + func testLens() { + let party = Party(h: User("max", 1, [], "one")) + let hostnameLens = Party.lpartyHost() • User.luserName() + + XCTAssert(hostnameLens.get(party) == "max") + + let updatedParty: Party = (Party.lpartyHost() • User.luserName()).set(party, "Max") + XCTAssert(hostnameLens.get(updatedParty) == "Max") + } +} diff --git a/FocusTests/UserExample.swift b/FocusTests/UserExample.swift new file mode 100644 index 0000000..1aec11f --- /dev/null +++ b/FocusTests/UserExample.swift @@ -0,0 +1,39 @@ +// +// UserExample.swift +// swiftz +// +// Created by Maxwell Swadling on 9/06/2014. +// Copyright (c) 2014 Maxwell Swadling. All rights reserved. +// + +import Focus + +// A user example +// an example of why we need SYB, Generics or macros +public class User { + let name : String + let age : Int + let tweets : [String] + let attr : String + + public init(_ n : String, _ a : Int, _ t : [String], _ r : String) { + name = n + age = a + tweets = t + attr = r + } + + // JSON + public class func create(x : String) -> Int -> ([String] -> String -> User) { + return { y in { z in { User(x, y, z, $0) } } } + } + + // lens example + public class func luserName() -> Lens { + return Lens { user in IxStore(user.name) { User($0, user.age, user.tweets, user.attr) } } + } +} + +public func ==(lhs : User, rhs : User) -> Bool { + return lhs.name == rhs.name && lhs.age == rhs.age && lhs.tweets == rhs.tweets && lhs.attr == rhs.attr +} diff --git a/README.md b/README.md index bb6e4b4..e708ac9 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,51 @@ # Focus -Optics for Swift +Focus is an Optics library for Swift (where Optics includes `Lens`, `Prism`s, and `Iso`s) that is +inspired by Haskell's [Lens](https://github.com/ekmett/lens) library. + +#Example + +```swift +import struct Focus.Lens +import struct Focus.IxStore + +//: A party has a host, who is a user. +final class Party { + let host : User + + init(h : User) { + host = h + } + + class func lpartyHost() -> Lens { + let getter = { (party : Party) -> User in + party.host + } + + let setter = { (party : Party, host : User) -> Party in + Party(h: host) + } + + return Lens(get: getter, set: setter) + } +} + +//: A Lens for the User's name. +extension User { + public class func luserName() -> Lens { + return Lens { user in IxStore(user.name) { User($0, user.age, user.tweets, user.attrs) } } + } +} + +//: Let's throw a party now. +let party = Party(h: User("max", 1, [], Dictionary())) + +//: A lens for a party host's name. +let hostnameLens = Party.lpartyHost() • User.luserName() + +//: Retrieve our gracious host's name. +let name = hostnameLens.get(party) // "max" + +//: Our party seems to be lacking in proper nouns. +let updatedParty = (Party.lpartyHost() • User.luserName()).set(party, "Max") +let properName = hostnameLens.get(updatedParty) // "Max" +``` \ No newline at end of file