Hızlı okuyuculara saygı duymak için önce kesin tanımla başlarım, daha hızlı "düz İngilizce" açıklamasıyla devam edip örneklere geçiyorum.
İşte biraz kısa ve öz bir tanım :
Bir monad (bilgisayar biliminde) resmen şu şekildedir:
X
belirli bir programlama dilinin her türünü yeni bir türe gönderir T(X)
("içindeki T
değerler içeren hesaplamaların türü" olarak adlandırılır X
);
formun iki işlevini f:X->T(Y)
ve g:Y->T(Z)
bir işlevi oluşturmak için bir kural ile donatılmış
g∘f:X->T(Z)
;
belli bir birim işlev ile ilgili olarak açık bir şekilde birleştirici ve çağrışımcı olmayan bir şekilde, pure_X:X->T(X)
bu değeri döndüren saf hesaplamaya bir değer kattığı düşünülmelidir.
Yani basit bir deyişle, bir monad bir olan her türünden geçmesine kural X
başka bir türeT(X)
ve bir kuralı iki işlevlerden geçmesine f:X->T(Y)
ve g:Y->T(Z)
yeni işleve (eğer oluşturmak istiyorum ama yapamıyor)h:X->T(Z)
. Bununla birlikte, katı matematiksel anlamda kompozisyon değildir . Temelde fonksiyonun kompozisyonunu "büküyoruz" ya da fonksiyonların nasıl oluştuğunu yeniden tanımlıyoruz.
Ayrıca, monad'ın "bariz" matematiksel aksiyomları karşılamak için besteleme kuralına ihtiyacımız var:
- Birleşim : Oluşturma
f
ile g
ve daha sonra h
(dışarıdan) oluşturma ile aynı olması gerekir g
ile h
ve daha sonra f
(içeriden).
- Unital özellik : Her iki tarafta kimlik fonksiyonu
f
ile bestelemek verim vermelidir .f
Yine, basit bir deyişle, fonksiyon kompozisyonumuzu istediğimiz gibi yeniden tanımlayarak deliremeyiz:
- Öncelikle ilişkilendirmeye, örneğin üst üste birkaç işlev oluşturabilmek
f(g(h(k(x)))
ve sipariş oluşturma işlev çiftlerini belirtme konusunda endişelenmemek gerekir. Monad kuralı, sadece bir çift fonksiyonun nasıl oluşturulacağını öngördüğü için , bu aksiyom olmadan, ilk önce hangi çiftin oluştuğunu bilmemiz gerekir. (Bu Yerdeğiştirme özelliğinden farklı olan Not f
ile oluşan g
olarak aynıydı g
ile oluşan f
halen uygulanmakta olduğu gibi).
- İkincisi, unital mülkiyete ihtiyacımız var, yani kimliklerin önemsiz bir şekilde onları beklediğimiz şekilde oluşturduğunu söylemek. Böylece, bu kimlikler çıkartıldığında işlevleri güvenle yeniden düzenleyebiliriz.
Kısaca tekrar: Bir monad, iki aksiyomu - ilişkilendirilebilirlik ve unital özellik - tatmin eden tür genişletme ve oluşturma işlevleri kuralıdır.
Pratik anlamda, monad'ın sizin için fonksiyon oluşturmaya özen gösterecek dil, derleyici veya çerçeve ile sizin için uygulanmasını istersiniz. Böylece, uygulamalarının nasıl uygulandığından endişelenmek yerine, işlevinizin mantığını yazmaya odaklanabilirsiniz.
Kısacası budur.
Profesyonel matematikçi olmak, çağıran kaçınmayı tercih h
"tertibi" f
ve g
. Çünkü matematiksel olarak değil. "Kompozisyon" olarak adlandırmak, yanlış bir h
şekilde gerçek matematiksel kompozisyon olduğunu varsayar . Hatta benzersiz tarafından belirlenmez f
ve g
. Bunun yerine, monadımızın yeni "besteleme kuralı" fonksiyonlarının bir sonucudur. İkincisi olsa bile gerçek matematiksel kompozisyondan tamamen farklı olabilir!
Daha az kuru yapmak için, küçük bölümlerle açıklama eklediğimden örnek göstermeye çalışalım, böylece doğrudan noktaya atlayabilirsiniz.
Monad örnekleri olarak istisna atma
İki işlev oluşturmak istediğimizi varsayalım:
f: x -> 1 / x
g: y -> 2 * y
Ancak f(0)
tanımlanmamıştır, bu nedenle bir istisna e
atılır. O zaman kompozisyon değerini nasıl tanımlayabilirsiniz g(f(0))
? Tabii ki yine bir istisna atın! Belki de aynı e
. Belki yeni bir güncellenmiş istisna e1
.
Burada tam olarak ne oluyor? İlk olarak, yeni istisna değerlerine (farklı veya aynı) ihtiyacımız var. Onları nothing
ya null
da herhangi bir şeyi çağırabilirsiniz, ancak öz aynı kalır - bunlar yeni değerler olmalı number
, örneğin buradaki örneğimizde bir olmamalıdır . Herhangi bir dilde null
nasıl null
uygulanabileceği konusunda kafa karışıklığını önlemek için onları aramamayı tercih ederim . Aynı şekilde kaçınmayı tercih ederim, nothing
çünkü null
prensip olarak ne null
yapılması gerektiği ile ilişkilidir , ancak bu prensip pratik nedenlerden ötürü sıklıkla bükülür.
İstisna tam olarak nedir?
Bu, deneyimli bir programcı için önemsiz bir konudur, ancak sadece herhangi bir karışıklık solucanını söndürmek için birkaç kelime bırakmak istiyorum:
İstisna, geçersiz yürütme sonucunun nasıl gerçekleştiği hakkında bilgi içeren bir nesnedir.
Bu, herhangi bir ayrıntıyı atmaktan ve tek bir küresel değer döndürmek ( NaN
veya gibi null
) veya uzun bir günlük listesi oluşturmak veya tam olarak ne olduğu, bir veritabanına göndermek ve dağıtılmış veri depolama katmanının her yerinde çoğaltmak;)
Bu iki istisna örneği arasındaki önemli fark, ilk durumda hiçbir yan etkinin olmamasıdır . İkincisinde var. Bu da bizi (bin dolar) sorusuna getiriyor:
Saf işlevlerde istisnalara izin veriliyor mu?
Daha kısa cevap : Evet, ancak sadece yan etkilere yol açmadıkları zaman.
Daha uzun cevap. Saf olmak için, işlevinizin çıktısı girdisi tarafından benzersiz bir şekilde belirlenmelidir. Bu nedenle , istisna dediğimiz yeni soyut değere f
göndererek işlevimizi değiştiriyoruz . Değerin , girdimiz tarafından benzersiz bir şekilde belirlenmeyen hiçbir dış bilgi içermediğinden emin oluruz . İşte yan etkisi olmayan bir istisna örneği:0
e
e
x
e = {
type: error,
message: 'I got error trying to divide 1 by 0'
}
Ve burada yan etkisi olan bir tane var:
e = {
type: error,
message: 'Our committee to decide what is 1/0 is currently away'
}
Aslında, sadece bu mesaj gelecekte değişebiliyorsa yan etkileri vardır. Ancak asla değişmeyeceği garanti edilirse, bu değer benzersiz bir şekilde öngörülebilir hale gelir ve bu nedenle yan etki yoktur.
Daha da keskin yapmak için. 42
Hiç geri dönen bir fonksiyon açıkça saftır. Ama eğer birileri 42
bu değerin değişebileceği bir değişken yapmaya karar verirse , aynı işlev yeni koşullar altında saf olmayı bırakır.
Özü göstermek için basitlik için nesne değişmez gösterim kullandığımı unutmayın. Ne yazık ki işler, error
fonksiyon kompozisyonu açısından burada istediğimiz gibi davranan bir tür olmayan JavaScript gibi dillerde dağılmışken, gerçek türler bu şekilde davranıyor null
veya NaN
davranmıyor, aksine bazı yapay ve her zaman sezgisel değil dönüşümleri yazın.
Tip uzantısı
İstisnamızın içindeki mesajı değiştirmek istediğimizden, E
istisna nesnesinin tamamı için gerçekten yeni bir tip ilan ediyoruz ve o zaman maybe number
, türden number
veya yeni istisna tipinden olan kafa karıştırıcı adının yanı sıra, bu ne yapar E
bu yüzden gerçekten birliktir number | E
arasında number
ve E
. Özellikle, E
ne önerilen ne de isme yansıyan , nasıl inşa etmek istediğimize bağlıdır maybe number
.
Fonksiyonel kompozisyon nedir?
Fonksiyonları alan f: X -> Y
ve g: Y -> Z
kompozisyonlarını fonksiyon h: X -> Z
doyurucu olarak inşa eden matematiksel işlemdir
h(x) = g(f(x))
. Bu tanımdaki sorun, sonucun f(x)
argümanı olarak kullanılmasına izin verilmediğinde ortaya çıkar g
.
Matematikte bu işlevler fazladan çalışma olmadan oluşturulamaz. Yukarıdaki örneğimiz için kesinlikle matematiksel çözüm f
ve tanım kümesinden g
kaldırmaktır . Bu yeni tanım kümesiyle (daha kısıtlayıcı yeni tür ), birleştirilebilir hale gelir .0
f
x
f
g
Bununla birlikte, programlamada f
böyle bir tanım kümesini kısıtlamak çok pratik değildir . Bunun yerine istisnalar kullanılabilir.
Ya da başka bir yaklaşım olarak, yapay değerler gibi oluşturulur NaN
, undefined
, null
, Infinity
değerlendirip Yani vb 1/0
için Infinity
ve 1/-0
için -Infinity
. Ve sonra yeni değeri istisna atmak yerine ifadenize zorlayın. Tahmin edilebilir bulabileceğiniz veya bulamayacağınız sonuçlara yol açar:
1/0 // => Infinity
parseInt(Infinity) // => NaN
NaN < 0 // => false
false + 1 // => 1
Ve devam etmeye hazır normal sayılara geri döndük;)
JavaScript, yukarıdaki örnekte olduğu gibi hata atmadan herhangi bir maliyetle sayısal ifadeleri yürütmemizi sağlar. Bu, işlevlerin oluşturulmasına da izin verdiği anlamına gelir. Monad tam olarak bununla ilgilidir - bu cevabın başında tanımlandığı gibi aksiyomları tatmin eden fonksiyonlar oluşturmak bir kuraldır.
Ancak, JavaScript'in sayısal hatalarla başa çıkma uygulamasından doğan işlev oluşturma kuralı bir monad mı?
Bu soruyu cevaplamak için ihtiyacınız olan tek şey aksiyomları kontrol etmektir (burada sorunun bir parçası olarak egzersiz olarak bırakılır;).
Fırlatma istisnası bir monad inşa etmek için kullanılabilir mi?
Gerçekten de, daha yararlı bir monad bunun yerine f
, bazıları için istisna atarsa x
, kompozisyonunun herhangi biriyle olduğu gibi reçete eden kural olacaktır g
. Ayrıca, istisnayı E
şimdiye kadar sadece bir olası değerle ( kategori teorisindeki terminal nesnesi ) global olarak benzersiz kılın . Şimdi iki aksiyom anında kontrol edilebilir ve çok kullanışlı bir monad elde ederiz. Ve sonuç, belki de monad olarak bilinen şeydir .