[Struktur Aljabar] functionM / Power Query M (Filter & Sort)

Muhammad Alfiansyah
3 min readSep 18, 2022

--

Photo by Pawel Czerwinski on Unsplash

Jangan jadi Bodoh karena orang bangun dengan perasaan yang berbeda setiap harinya

Ide untuk melakukan sorting atau filtering adalah dengan membuat predicate. Dimana predicate merupakan fuction type A yang akan mereturn Boolean. Untuk itu kita perlu mendefinisikan typealias Predicate.

typealias Predicate<A> = FunctionM<A, Bool>

Maksudnya kita dapat take function apapun dan selalu me-return Boolean.

Nah untuk melakukan hal tersebut apa itu functionM ?

Saya coba cari definisi functionM dan berakhir pada Power Query M formula punya Microsoft, nggak tau mereka adalah benda yang sama atau kebetulan punya definisi yang mirip yaitu

A core capability of Power Query is to filter and combine, that is, to mash-up data from one or more of a rich collection of supported data sources.

In the Power Query M formula language, a function is a mapping from a set of input values to a single output value

Untuk mefilter dan menggabungkan dengan cara memapping set input value menjadi satu output value.

Saya nggak mengiyakan atau sebaliknya kalo functionM disini adalah Power Query M tapi karena mempunyai tujuan yang sama jadi saya masukan ke sini untuk kita ulik lebih dalam lagi selanjutnya.

Oke kembali lagi ke functionM tadi jadi bagaimana bentuk functionM ini ?jadi functionM ini juga inherit dari Monoid.

struct FunctionM<A, M: Monoid>: Monoid {
let call: (A) -> M
static var e: FunctionM {
return FunctionM { _ in M.e }
}
static func <> (lhs: FunctionM, rhs: FunctionM) -> FunctionM {
return FunctionM { a in
return lhs.call(a) <> rhs.call(a)
}
}
}

Lets check our code

let isEven = Predicate<Int> { $0 % 2 == 0 }func isLessThan<C: Comparable>(_ c: C) -> Predicate<C> {
return Predicate { $0 < c }
}

Filter

Selanjutnya masuk ke filter array

extension Array {
func filtered(by predicate: Predicate<Element>) -> [Element] {
return self.filter(predicate.call)
}
}
[2,3,4].filtered(by: isEven <> isLessThan(10)) // result 2,4

Concat

[2,3,4].filtered(by: concat([isEven, isLessThan(10)]))

Ordering

enum Ordering: Monoid {
case lt
case eq
case gt

static var e: Ordering {
return .eq
}

static func <> (lhs: Ordering, rhs: Ordering) -> Ordering {
switch (lhs, rhs) {
case (.lt, _): return .lt
case (.gt, _): return .gt
case (.eq, _): return rhs
}
}
}
typealias Comparator<A> = FunctionM<(A, A), Ordering>extension Comparable {
static func comparator() -> Comparator<Self> {
return Comparator { lhs, rhs in
return lhs < rhs ? .lt : lhs > rhs ? .gt : .eq
}
}
}
extension Array {
func sorted(by comparator: Comparator<Element>) -> Array {
return self.sorted { comparator.call(($0, $1)) == .lt }
}
}
[1,4,6,3].sorted(by: Int.comparator()) // result 1,3,4,6 ------------
[REVERSED]extension Ordering {
func reversed() -> Ordering {
return self == .lt ? .gt : self == .gt ? .lt : .eq
}
}
extension FunctionM where M == Ordering {
func reversed() -> FunctionM {
return FunctionM { self.call($0).reversed() }
}
}

Whats Next ?

Selanjutnya mungkin kita akan masuk Lenses dan Prism :). Semoga membantu !!!!!!

--

--

No responses yet