Bir fonksiyonun aldığı argüman sayısıdır. Bir fonksiyon aldığı argüman sayısına göre unary (1 argüman), binary (2 argüman), ternary (3 argüman)... olarak adlandırılır. Eğer bir fonksiyon değişken sayıda argüman alıyorsa variadic olarak adlandırılır.
Prelude> let sum a b = a + b
Prelude> :t sum
sum :: Num a => a -> a -> a
-- sum fonksiyonunun arity'si 2dir.
Argüman olarak bir fonksiyon alan ya da bir fonksiyonu çıktı veren fonksiyonlardır.
Prelude> let add3 a = a + 3
Prelude> map add3 [1..4]
[4,5,6,7]
Prelude> filter (<4) [1..10]
[1,2,3]
Kapanış, bir fonksiyona bağlı değişkenleri koruyan bir kapsamdır. Kısmi uygulama için önemlidir.
Prelude> let f x = (\y -> x + y)
f
fonksiyonunu bir sayı ile çağıralım.
Prelude> let g = f 5
Bu durumda x = 5
değeri g
fonksiyonunun kapanışında korunur. Şimdi g
fonksiyonunu bir y
değeri ile çağırırsak:
Prelude> g 3
8
Kısmi uygulama, bir fonksiyonun bazı argümanlarını önceden doldurarak yeni bir fonksiyon oluşturmaktır.
-- Orjinal fonksiyonumuz
Prelude> let add3 a b c = a + b + c
--`2` ve `3` argümanlarını `add3` fonksiyonumuza vererek `fivePlus` fonksiyonumuzu oluşturuyoruz
Prelude> let fivePlus = add3 2 3
Prelude> fivePlus 4
9
Kısmi uygulama, kompleks fonksiyonlardan daha basit fonksiyonlar oluşturmaya yardım eder. Curried fonksiyonlar otomatik olarak kısmi uygulanmış fonksiyonlardır.
Birden çok parametre alan bir fonksiyonu, her defasında sadece bir parametre alan bir fonksiyona dönüştürmektir.
Fonksiyon her çağrıldığında sadece bir argüman kabul eder ve tüm argümanlar verilene kadar sadece bir argüman alan bir fonksiyon döndürür.
Prelude> let sum (a, b) = a + b
Prelude> let curriedSum = curry sum
Prelude> curriedSum 40 2
42
Prelude> let add2 = curriedSum 2
Prelude> add2 10
12
İki farklı fonksiyonu bir araya getirerek, bir fonksiyonun çıktısı diğer fonksiyonun girdisi olan üçüncü bir fonksiyon oluşturmaktır.
-- fonksiyonları bir araya getirmek için '.' operatörü kullanılır
Prelude> let floorAndToString = show . floor
Prelude> floorAndToString 32.123
"32"
Bir fonksiyonun çıktısı sadece girdi veya girdilerine bağlı ve fonksiyon yan etki oluşturmuyor ise, fonksiyon saftır denir.
Prelude> let greet name = "Hello " ++ name
Prelude> greet "Brianne"
"Hello Brianne"
Saf olmayan fonksiyona bir örnek:
Prelude> let name1 = "Brianne"
Prelude> let greet = "Hello " ++ name1
Prelude> greet
"Hello Brianne"
Yukarıdaki fonksiyonun çıktısı fonksiyonun dışarısında tanımlı bir değişkene bağlıdır.
Bir fonksiyon veya ifade, dışarısındaki bir durum ile etkileşime geçiyor ise (okuma veya yazma), yan etki ye sahiptir denir.
Haskell'deki tüm fonksiyonlar saftır.
Bir fonksiyon, sonucuna tekrar uygulandığında sonuç değişmiyorsa idempotent olarak adlandırılır.
f(f(x)) ≍ f(x)
Prelude> abs (abs (-1))
1
Prelude Data.List> sort (sort [1,4,3,1,5])
[1,1,3,4,5]
Argümanların açıkca tanımlanmadığı fonksiyonlar yazmaktır. Tacit programming olarak da bilinir.
Prelude> let add a b = a + b
-- incrementAll fonksiyonunu tanımlayalım
-- Point-free değildir - `numbers` argümanı belirtilmiştir
Prelude> let incrementAll numbers = map (+1) numbers
-- Point-free - Fonksiyonun aldığı argüman açıkca belirtilmemiştir
Prelude> let incrementAll = map (+1)
incrementAll
fonksiyonunun numbers
argümanını aldığı belirtilmiştir, bu nedenle point-free değildir. incrementAll2
fonksiyonu ise, fonksiyon ve değerlerin bir bileşimidir ve argüman bilgisi belirtilmemiştir. Yani point-free dir.
Verilen bir değer için doğru veya yanlış değerini dönen fonksiyonlardır. Genellikle filter ile beraber kullanılırlar.
Prelude> let predicate a = a < 3
Prelude> filter predicate [1..10]
[1,2]
Kategory teorisinde bir kategori, matematiksel yapılar ve bunlar arasında tanımlı morfizmlerden oluşur. Programlamada ise, tipler matematiksel yapılar, fonksiyonlar ise morfizmlerdir.
Bir kategori aşağıdaki üç koşulu sağlar:
- Bir yapıyı kendisine eşleyen bir birim morfizm vardır. Yani
a
herhangi bir kategori içinde bir yapı ise,a -> a
şeklinde tanımlı bir fonksiyon vardır. a
,b
vec
herhangi bir kategori içindeki yapılar vef : a -> b
veg : b -> c
iseh : a -> c
,h(x)=(g • f)(x)=g(f(x))
vardır.f • (g • h)
ve(f • g) • h
ifadeleri aynıdır.
Daha Fazla Kaynak
map
fonksiyonunu implemente eden bir nesnedir ve aşağıdaki iki özelliği sağlar:
Identity
object.map(x => x) ≍ object
Composable
object.map(compose(f, g)) ≍ object.map(g).map(f)
Her a
tipi için
of :: a -> F a
ile tanımlı bir of
fonksiyonuna sahip F
funktoruna denir.
Bir ifade değeri ile yer değiştirildiğinde programın davranışı değişmiyor ise, ifade referentially transparent olarak adlandırılır.
Anonim (isimsiz) fonksiyonlardır.
\x -> x + 1
Çoğunlukla yüksek mertebeden fonksiyonlar ile birlikte kullanılırlar.
Prelude> map (\x -> x + 1) [1..4]
[2,3,4,5]
Lazy evaluation, bir ifadenin, ifade sonucuna ihtiyaç duyulana kadar hesaplanmamasıdır. Böylece, sonsuz listeler gibi yapılar tanımlanabilir.
Prelude> let lst0 = [1..]
Prelude> take 5 lst0
[1,2,3,4,5]
Bir nesneyi aynı tip başka bir nesne ile birleştiren bir fonksiyona sahip bir objedir.
Basit bir monoid örneği sayıların toplanmasıdır:
1 + 1 -- 2
Bu durumda sayılar nesneler, +
operatörü ise fonksiyondur.
Birim eleman olmak zorundadır,
Toplama işleminin birim elemanı 0
dır.
1 + 0 -- 2
ve geçişkenlik özelliği de gereklidir (associativity):
1 + (2 + 3) == (1 + 2) + 3
of
ve chain
fonksiyonlarına sahip bir nesne monad olarak adlandırılır.
// Implementation
Array.prototype.chain = function (f) {
return this.reduce((acc, it) => acc.concat(f(it)), [])
}
// Usage
Array.of('cat,dog', 'fish,bird').chain((a) => a.split(',')) // ['cat', 'dog', 'fish', 'bird']
// Contrast to map
Array.of('cat,dog', 'fish,bird').map((a) => a.split(',')) // [['cat', 'dog'], ['fish', 'bird']]
of
fonksiyonu bazı fonksiyonel programlama dillerinde return
olarak;
chain
fonksiyonu ise flatmap
ve bind
olarak geçmektedir.
extract
ve extend
fonksiyonlarına sahip bir nesnedir.
const CoIdentity = (v) => ({
val: v,
extract () {
return this.val
},
extend (f) {
return CoIdentity(f(this))
}
})
Extract fonksiyonu bir değeri funktorun dışına çıkarır.
CoIdentity(1).extract() // 1
Extend fonksiyonu comonad üzerinde bir fonksiyon çalıştırır. Fonksiyonun çıktı tipi comonad ile aynıdır.
CoIdentity(1).extend((co) => co.extract() + 1) // CoIdentity(2)
Applicative functor, ap
fonksiyonuna sahip bir nesnedir. ap
fonksiyonu nesnedeki bir fonksiyonu, aynı tipte başka bir nesnedeki bir değere uygular.
// Implementation
Array.prototype.ap = function (xs) {
return this.reduce((acc, f) => acc.concat(xs.map(f)), [])
}
// Example usage
;[(a) => a + 1].ap([1]) // [2]
Bir dönüşüm fonksiyonudur.
Girdi ve çıktı tipinin aynı olduğu fonksiyonlardır.
// uppercase :: String -> String
const uppercase = (str) => str.toUpperCase()
// decrement :: Number -> Number
const decrement = (x) => x - 1
İki farklı tipteki nesne arasındaki bir dönüşüm ve ters dönüşüm çiftidir.
// Providing functions to convert in both directions makes them isomorphic.
const pairToCoords = (pair) => ({x: pair[0], y: pair[1]})
const coordsToPair = (coords) => [coords.x, coords.y]
coordsToPair(pairToCoords([1, 2])) // [1, 2]
pairToCoords(coordsToPair({x: 1, y: 2})) // {x: 1, y: 2}
equals
fonksiyonuna (aynı tipler arasında karşılaştırma yapmaya imkan veren) sahip bir nesnedir.
Array.prototype.equals = function (arr) {
const len = this.length
if (len !== arr.length) {
return false
}
for (let i = 0; i < len; i++) {
if (this[i] !== arr[i]) {
return false
}
}
return true
}
;[1, 2].equals([1, 2]) // true
;[1, 2].equals([0]) // false
Bir nesneyi aynı tipteki başka bir nesne ile birleştirmeye imkan veren concat
fonksiyonuna sahip bir nesnedir.
;[1].concat([2]) // [1, 2]
bir yapıyı tek bir değere dönüştüren reduce
fonksiyonuna sahip bir nesnedir.
const sum = (list) => list.reduce((acc, val) => acc + val, 0)
sum([1, 2, 3]) // 6
Bileşke veri tipleridir - başka tiplerin bir araya gelmesiyle oluşur. En yaygın cebirsel veri tipleri toplamsal tipler ve çarpımsal tiplerdir.
P.S: This repo is successful due to the wonderful contributions!