Last active
September 21, 2020 07:38
-
-
Save haifengkao/4473173790ac3d74ced7c9f09f27eefe to your computer and use it in GitHub Desktop.
point free exercise
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
infix operator <<<: CompositionPrecedence | |
precedencegroup CompositionPrecedence { | |
associativity: left | |
} | |
public func <<<<A, B, C>( | |
_ g: @escaping (B) -> C, | |
_ f: @escaping (A) -> B | |
) -> (A) -> C { | |
{ a in g(f(a)) } | |
} | |
precedencegroup FunctorPrecedence { | |
associativity: left | |
higherThan: DefaultPrecedence | |
} | |
/// Ap | Applies a function encapsulated by a functor to the value encapsulated by another functor. | |
infix operator <*> : FunctorPrecedence | |
/// Fmap | Maps a function over the value encapsulated by a functor. | |
infix operator <^> : FunctorPrecedence | |
/// Fmap | If the Optional is `.None`, ignores the function and returns `.None`. Else if the | |
/// Optional is `.Some`, applies the function to its value and returns the result in a new `.Some`. | |
public func <^> <A, B>(f : (A) -> B, a : A?) -> B? { | |
return a.map(f) | |
} | |
/// Ap | Returns the result of applying the given Optional function to a given Optional value. If | |
/// the function and value both exist the result is the function applied to the value. Else the | |
/// result is `.None`. | |
/// | |
/// Promotes function application to an Optional function applied to an Optional value. | |
public func <*> <A, B>(f : ((A) -> B)?, a : A?) -> B? { | |
return f.flatMap { $0 <^> a } | |
} | |
/// Curries a 2-ary function. | |
/// | |
/// - Parameter fun: Function to be curried. | |
/// - Returns: `fun` in curried form. | |
public func curry<A, B, C>(_ fun: @escaping (A, B) -> C) -> (A) -> (B) -> C { | |
{ a in { b in fun(a, b) }} | |
} | |
func isMultiple(other: Int, n: Int) -> Bool { | |
return n.isMultiple(of: other) | |
} | |
let isMultipleOf3 = curry(isMultiple(other:n:))(3) | |
let isMultipleOf5 = curry(isMultiple(other:n:))(5) | |
let fizz = {$0 ? "fizz" : nil} <<< isMultipleOf3 | |
let buzz = {$0 ? "buzz" : nil} <<< isMultipleOf5 | |
func merge(x: String?, y: String?) -> String? { | |
x?.appending(y ?? "") ?? y | |
} | |
func fizzbuzz(n: Int) -> String { | |
let a = fizz(n) | |
let b = buzz(n) | |
return (curry(merge(x:y:))(a)(b)) ?? n.description | |
} | |
(1...20).map(fizzbuzz) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment