Skip to content

Instantly share code, notes, and snippets.

@TizianoCoroneo
Last active December 28, 2017 21:46
Show Gist options
  • Save TizianoCoroneo/7567c0377b7cecf12230d11324956ed4 to your computer and use it in GitHub Desktop.
Save TizianoCoroneo/7567c0377b7cecf12230d11324956ed4 to your computer and use it in GitHub Desktop.
Haskell style List Comprehensions in Swift 4
import Foundation
typealias Format<A, B> = Component<A, B>
typealias Source<A> = Component<A, A>
typealias Filter<A> = Component<A, A>
enum Component<A, B> {
case format((A) -> B)
case sources([A])
case filter((A) -> Bool)
}
struct ListComprehension<A, B> {
let formats: [Format<A, B>]
let sources: [Source<A>]
let filters: [Filter<A>]
var elements: [A] {
return sources.map {
switch $0 {
case .sources(let elems): return elems
default: return []
}
}.reduce([], +)
}
var filterFunctions: [(A) -> Bool] {
return self.filters.map {
switch $0 {
case .filter(let fil): return [fil]
default: return []
}
}.reduce([], +)
}
var filteredElements: [A] {
return elements.filter { el in
return filterFunctions.map { filter in
return filter(el)
}.reduce(true, { $0 && $1 })
}
}
var result: [B] {
return filteredElements.flatMap { el in
return formats.flatMap { format in
switch format {
case .format(let f):
return f(el)
default:
return nil
}
}
}
}
struct Compute {
let comprehension: ListComprehension<A, B>
}
}
precedencegroup ListComponents {
higherThan: ListCreate
}
precedencegroup ListCreate {}
infix operator |: ListCreate
prefix operator <-
infix operator &&&: ListComponents
prefix operator ?!
prefix operator %
prefix operator |-
postfix operator -|
func |<A, B>(_ lhs: Format<A, B>, _ rhs: [Component<A, A>]) -> ListComprehension<A, B> {
return ListComprehension(formats: [lhs], sources: rhs, filters: rhs)
}
func |<A, B>(_ lhs: [Format<A, B>], _ rhs: [Component<A, A>]) -> ListComprehension<A, B> {
return ListComprehension(formats: lhs, sources: rhs, filters: rhs)
}
func |<A, B>(_ lhs: [Format<A, B>], _ rhs: Component<A, A>) -> ListComprehension<A, B> {
return ListComprehension(formats: lhs, sources: [rhs], filters: [rhs])
}
func |<A, B>(_ lhs: Format<A, B>, _ rhs: Component<A, A>) -> ListComprehension<A, B> {
return ListComprehension(formats: [lhs], sources: [rhs], filters: [rhs])
}
prefix func |-<A, B>(_ rhs: ListComprehension<A, B>) -> ListComprehension<A, B>.Compute {
return ListComprehension<A, B>.Compute.init(comprehension: rhs)
}
prefix func |-<A, B>(_ rhs: () -> ListComprehension<A, B>) -> ListComprehension<A, B>.Compute {
return |-rhs()
}
prefix func |-<A, B>(_ rhs: ListComprehension<A, B>.Compute) -> [B] {
return rhs.comprehension.result
}
postfix func -|<A, B>(_ lhs: ListComprehension<A, B>) -> ListComprehension<A, B>.Compute {
return ListComprehension<A, B>.Compute.init(comprehension: lhs)
}
postfix func -|<A, B>(_ lhs: () -> ListComprehension<A, B>) -> ListComprehension<A, B>.Compute {
return lhs()-|
}
postfix func -|<A, B>(_ lhs: ListComprehension<A, B>.Compute) -> [B] {
return lhs.comprehension.result
}
func &&&<A, B>(_ lhs: [Component<A, B>], _ rhs: Component<A, B>) -> [Component<A, B>] {
return lhs + [rhs]
}
func &&&<A, B>(_ lhs: Component<A, B>, _ rhs: Component<A, B>) -> [Component<A, B>] {
return [lhs, rhs]
}
func &&&<A, B>(_ lhs: Component<A, B>, _ rhs: [Component<A, B>]) -> [Component<A, B>] {
return [lhs] + rhs
}
func &&&<A, B>(_ lhs: [Component<A, B>], _ rhs: [Component<A, B>]) -> [Component<A, B>] {
return lhs + rhs
}
prefix func <-<A>(_ c: [A]) -> Source<A> {
return Source<A>.sources(c)
}
prefix func ?!<A>(_ filter: @escaping (A) -> Bool) -> Filter<A> {
return Filter<A>.filter(filter)
}
prefix func %<A, B>(_ f: @escaping (A) -> B) -> Format<A, B> {
return Format<A, B>.format(f)
}
let formats = %{ $0 * $0 } &&& %{ $0 + 1 }
let sources = <-Array(1..<10) &&& <-[20, 30, 40]
let filters = ?!{ $0 % 2 == 0 } &&& ?!{ $0 != 4 }
let list = formats | sources &&& filters
let result = |-list-|
let result2: [Int] = |-{ %{$0} | <-[1, 2, 3, 4, 5] &&& ?!{ $0 % 2 == 0 } }-|
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment