Photo by Tiago Fioreze on Unsplash

JS ILE FONKSIYONEL PROGRAMLAMA

Functors ve Categories

Functors mappable arayüzünden türemiş map() fonksiyonuna sahip yapısını map ile değiştirmeyen ama içeriğini güncelleten veri türüdür.

--

Bu yazıyı daha önceden yazmış olduğum JS ile Fonksiyonel Programlama yazısının bir devamı olarak yazıyorum. Bir çok kavramı tek bir yazıda ele almanın yaratacağı karmaşıklıktan ve okunma zorluğundan kaçmak için yazılarımı bölümler halinde yazma kararı verdim.

1. Functor Nedir ?

Bir önceki yazımda ADT (Abstract Data Types) bahsetmiştim. Functor da bir veri tipidir. Bir Değer, String, Array, Object, Stream, Promise vb yapısını bozmadan içeriğini başka bir Değer, String, Array, Object, Stream, Promise Map etmeyi sağlıyorsa bu Functor veri tipindedir.

https://github.com/fantasyland/fantasy-land

Konunun karmaşık geldiğinin farkındayım. Daha basit bir şekilde anlatmak için örnekler ile anlatmaya çalışacağım. mappable interface türemiş .map() fonksiyonuna sahip olan veri tipleri/container diyebiliriz.

Konuyu biraz örnekler ile anlatırsak daha iyi bir şekilde anlaşılacağını düşünüyorum.

Array Functor

Array Functor veri tipidir. Çünkü map fonksiyonu vardır ve buna istediğimiz fonksiyonları vererek arka arkaya map fonksiyonu çağırabiliriz. Array yapısı ve eleman sayısı değişmez ama içeriği değişmiş olur. Önce square fonksiyonu ile karesini alıp sonra bu sayılara +1 ekliyoruz.

Array Functor

Bunun diğer bir yöntemide map().map() yapmak yerine fonksiyonların bir birini compose etmesi yani sağlayarak tek bir map fonksiyonu içerisinde istenileni yapabilirsiniz.

h = f(g(x))

Function Functor

h fonksiyonu f(g(x)) ile oluşturabildik ama acaba fonksiyonuda map() ile yapısını dönüştürmeden çalışma mantığını değiştirebilir miyiz ? Cevap Evet.

Function Functor

String Functor

Örneğin String her bir karakterini alıp bunu bir uppercase fonksiyonundan sonradan da Sesli Harfleri 0 dönüştürme fonksiyonundan geçirebiliriz.

Promise Functor

Promises .map() yerine .then() metodunu kullanarak async iç içe bir birini içeren promise kaplamaları oluşturarak aynı yapıda promise döner.

const waitThenCall = (msg) => { 
return new Promise((resolve, reject) => {
setTimeout(() => {resolve(msg + “success”) }, 1000)});}
waitThenCall(“Hello1_”)
.then((data) => { console.log(data)
return waitThenCall(“Hello2_”)}, (err)=>{})
.then((data) => { console.log(data)
return waitThenCall(“Hello3_”)}, undefined)
.then((data) => { console.log(data)})
.catch(err) => {console.log(err+"X")})

2. Functor Yasaları

Hayat bir çok pattern (örüntülerden) oluşmaktadır. Çiçek yapraklarında, gözde, kar tanesinde vb doğada bir çok örüntü bulunur. Kategori bir yapısı olmalıdır. Örneğin sırası olmalı Array sıralı yapılardır örneği .1 elemanlı bir bir kategori, 2 elemanlı ayrı bir kategoridir. Kategori Teoriside bu örüntülerin tanınmasını sağlar. Örneğin bir geometrik şeklin başla bir geometrik şekle map/dönüştürülmesidir. Bunu yapan Functor fonksiyonudur. Bunu yaparken yapısının yani nokta sayısının, eleman sayısının değişmediğini görebilirsiniz.

Morphism

Kategori Functor olabilmesi için aşağıdaki 2 temel yasayı koruması gerekir.

  1. Identity (Birim/Kendine dönme): f(x)=> x
  2. Composition (Kapsama): f(g(x)) = map(g).map(f)

Composition yasası bu bahsettiğimiz yapının (structure) korunduğunun göstergesidir. Aşağıdaki resimde bu durumu göstermeye çalıştım. Functor sayesinde (f . g) vektorel eşitliliğini görebilirsiniz. bu sayede map fonksiyonlarını arka arkaya çağırmak fonksiyon composition ile aynı değeri verir.

Functor Composition (Bartosz Milewski Category Theory)

Identity yasası yani birim fonksiyonun kendine gitmesi . : f(x)=> x

Functor Composition (Bartosz Milewski Category Theory)
Identity by Eric Elliott

3. Functor Ne İçin Kullanabiliriz ?

addOne fonksiyonu aşağıda kendisine verilen bir sayıyı +1 değeri ile toplayıp geriye dönen pure function

addOne fonksiyonu

Peki her zaman istediğimiz gibi çalışıyor mu ? Örneğin verdiğimiz argüman sayı değilde Object, String veya Array tipinde de olabilir bunların fonksiyonda düzgün sonuçlar üretmeyeceği bir gerçek.

Invalid Arguments

Bu tip girdileri kontrol etmek için number check koyabiliriz.

Ama yinede her matematiksel işlem (square, addTen, sum, multiply) için fonksiyonların içerisinde bu kontrollerin olması gerekecek. Bunu daha yapısal bir hale nasıl dönüştürebiliriz.

  • Argümanlar doğru tiplerde olmayabilir
  • Doğru tipte olsa bile içeride bir hata oluşturuyor olabilir.
  • İçeride kullanılacak değerler async callback elde ediliyor olabilir ve o an için bu değer hazır olmayabilir.

3.1 Type Functor (Örnek NumFunctor)

NumFunctor sayesinde numeric değerler için işlem yapabilirken , numeric olmayan işlemler için NaN dönmesini sağlayan fonksiyonu ortaklaştırmış olduk. Siz bunu String, Array vb versiyonlarını yapabilirsiniz.

Numeric Functor

3.2 Maybe Functor

İç içe olan nesne composition kapsamlarının null ve undefined check yaptığımız bir çok kod bulunur. Bunları MayBe Functor ile giderebiliriz. Bu sayede kod içerisinde defalarca bu kontrolleri yapan kodları tekrarlamamış oluruz.

if(user && user.univercity && user.univercity.name) // kontrolü koymamıza gerek kalmaz. Bu ve bunun gibi bütün null undefined check yapısal olarak kapsayabilecek bir Functor var. 
MayBe Functor

3.3 Either Functor

Left Identity olduğu, Right istenen fonksiyonu gerçekleştirdiği Either Functor oluşturabiliriz.

Either Left/Right

Peki bu Either ile tryCatch mekanizması kurmak istesek Right Functor, Left Functor ve bunları yöneten tryCatch fonksiyonu olsun. bu tryCatch fonksiyonunu istenilen her exception fırlatma fonksiyonunda kullanabiliriz artık.

try/catch mekanizması

4. Yorum

Fonksiyonel Programlamada Object Oriented programlamaya göre daha fazla kodlama pattern soyutlaştırma çabası var. Bu sayede olabildiğince tek bir şekilde ve kontrollü kod yazmak mümkün hale geliyor. Tüm kodunuza bu tip kontrol ekleyip bunlar dışında kod yazılmasına izin vermezseniz kodlayıcıları olabildiğince belli bir yolun içerisinde kod yazmaya zorlamış oluyorsunuz.

Object Oriented nesne/domain modelleri, hiyerarşileri ve ilişkileri üzerinde zorunluluklar getirirken, Functional Programming davranış modelleri, ortak kodlama tekrarlarını engelleyecek soyutlamalar üzerine zorunluluklar getirmeyi sağlıyor.

5. Referanslar

Okumaya Devam Et 😃

Bu yazının devamı veya yazı grubundaki diğer yazılara erişmek için bu linke tıklayabilirsiniz.

--

--