okların amacı nedir?


62

Haskell ile fonksiyonel programlamayı öğreniyorum ve ilk olarak neden onlara ihtiyacım olduğunu anlayarak kavramları yakalamaya çalışıyorum.

Fonksiyonel programlama dillerinde okların amacını bilmek istiyorum. Hangi sorunu çözüyorlar? Http://en.wikibooks.org/wiki/Haskell/Understanding_arrows ve http://www.cse.chalmers.se/~rjmh/afp-arrows.pdf adresini kontrol ettim . Tek anladığım, hesaplamalar için grafikleri tanımlamak için kullanıldıkları ve puansız stil kodlamasına daha kolay izin verdikleridir.

Makale, bu noktanın serbest stilinin anlaşılması ve yazılması genellikle daha kolay olduğunu varsayar. Bu bana oldukça öznel görünüyor. Başka bir makalede ( http://en.wikibooks.org/wiki/Haskell/StephensArrowTutorial#Hangman:_Main_program ) bir cellat oyunu uygulanmıştır, ancak okların bu uygulamayı doğal hale nasıl getirdiğini göremiyorum.

Konsepti tanımlayan birçok makale bulabilirim, ancak motivasyon hakkında hiçbir şey bulamadım.

Neyi özlüyorum?

Yanıtlar:


42

Partiye geç geldiğimin farkındayım, ama burada iki teorik cevabınız vardı ve çiğnemek için pratik bir alternatif sunmak istedim. Buna, yakın zamanda üzerinde çalıştığım bir proje için Arrows konusunda zorla yürüdüğü bir akraba Haskell noob olarak geliyorum.

İlk önce, Haskell'deki çoğu sorunu Oklar'a ulaşmadan verimli bir şekilde çözebilirsiniz. Bazı kayda değer Haskellers onları gerçekten sevmiyor ve kullanmıyor ( burada daha fazla bilgi için buraya , buraya ve buraya bakınız ). Öyleyse kendinize “Hey, bunlara ihtiyacım yok” diyorsanız, gerçekten doğru olabileceğinizi anlayın.

Onları ilk öğrendiğimde oklarla ilgili en sinir bozucu bulduğum şey, konuyla ilgili öğreticilerin kaçınılmaz olarak devre analojisi için ulaştığıydı. Ok koduna bakarsanız - şekerli çeşitlilik, en azından - bir Donanım Tanımlama Dili kadar hiçbir şeye benzemez. Girişleriniz sağda, çıkışlar solda sıralanıyor ve hepsini doğru bir şekilde bağlayamazsanız ateşlenmiyorlar. Kendi kendime düşündüm: Gerçekten mi? Burası bizim bittiğimiz yer mi? Tamamen yüksek seviyede bir dil yarattık mı, bir kez daha bakır tellerden ve lehimlerden oluşuyor mu?

Buna doğru cevap, belirleyebildiğim kadarıyla: Aslında, evet. Şu anda Arrows için katil kullanım davası FRP'dir (genel olarak Yampa'yı, oyunları, müziği ve reaktif sistemleri düşünün). FRP'nin karşılaştığı problem, büyük ölçüde, diğer tüm senkron mesajlaşma sistemlerinin karşı karşıya kaldığı aynı problemdir: sürekli bir girdi akışının, sürekli bir girdi akışına, ilgili bilgiyi veya yayılma sızıntılarını bırakmadan bağlanması. Akışları liste olarak modelleyebilirsiniz - bazı son FRP sistemleri bu yaklaşımı kullanır - ancak çok sayıda giriş varsa, listelerin yönetimi neredeyse imkansız hale gelir. Kendinizi şu anki durumdan yalıtmanız gerekir.

Okların FRP sistemlerinde izin verdiği şey, işlevlerin bir ağa bileşimidir; aynı zamanda, bu işlevler tarafından geçirilen temel değerlere yönelik herhangi bir referansı tamamen ortadan kaldırır. FP'de yeniyseniz, bu başlangıçta kafa karıştırıcı olabilir ve daha sonra bunun etkilerini yutturduğunuzda akıllara durgunluk verebilir. Ancak son zamanlarda, işlevlerin soyutlanabileceği fikrini ve [(*), (+), (-)]tür gibi bir listenin nasıl anlaşılacağını kabul ettiniz [(a -> a -> a)]. Oklarla, soyutlamayı bir kat daha ilerletebilirsin.

Bu soyut yetenek, kendi tehlikelerini de beraberinde getiriyor. Birincisi, GHC'yi tip varsayımlarınızdan ne yapacağını bilmediği köşe davalarına itebilir. Tür düzeyinde düşünmeye hazırlıklı olmanız gerekir - bu türler ve RankNTypes ve diğer konular hakkında bilgi edinmek için mükemmel bir fırsattır.

Ayrıca kodlayıcının bazı Ok birleştiricisine ulaştığı yerde “Aptal Ok Dublörleri” olarak adlandırdığım bir takım örnekler var; çünkü o, tüllerle temiz bir numara göstermek istiyor. (İşte deliliğe benim kendi önemsiz katkım .) Vahşi doğada karşılaştığınızda böyle sıcak dogging görmezden çekinmeyin.

NOT: Yukarıda belirttiğim gibi, göreceli bir noob. Yukarıdaki herhangi bir yanılgıyı bildirmişsem, lütfen beni düzeltmekten çekinmeyin.


2
Henüz bir şey kabul etmediğim için mutluyum. Bu cevabı verdiğiniz için teşekkür ederiz. Kullanıcılara daha fazla odaklanır. Örnekler harika. Öznel kısımlar açıkça tanımlanmış ve dengelenmiştir. Umarım bu soruyu aşan insanlar geri gelir ve bunu görürler.
Simon Bergot

Bağlantılı çözümünüz için oklar kesinlikle yanlış bir araç olsa da removeAt' n = arr(\ xs -> (xs,xs)) >>> arr (take (n-1)) *** arr (drop n) >>> arr (uncurry (++)) >>> returnA, bunun daha özlü ve net olarak yazılabileceğini söylememe ihtiyacım var removeAt' n = (arr (take $ n-1) &&& arr (drop n)) >>> (arr $ uncurry (++)).
cemper93

29

Bu biraz "yumuşak" bir cevaptır ve herhangi bir referansın bu şekilde ifade edip etmediğinden emin değilim, ama bu şekilde okları düşünmeye başladım:

Bir ok türü A b ctemelde bir fonksiyondur, b -> cancak monadik bir değerin M adüz eskiden daha fazla yapıya sahip olduğu şekilde daha fazla yapıya sahiptir a.

Şimdi bu ekstra yapının ne olduğu, bahsettiğiniz ok örneğine bağlı. Tıpkı monadlarda olduğu gibi IO ave Maybe aher birinin ek bir yapısı var.

Eğer monads ile almak şey bir gitmek için bir yetersizlik olduğu M abir etmek a. Şimdi bu bir sınırlama gibi görünebilir, ancak aslında bir özelliktir: tür sistemi sizi monadik bir değeri düz eski bir değere dönüştürmekten korumaktadır. Bu değeri yalnızca monad aracılığıyla >>=veya belirli monad örneğinin ilkel işlemleri üzerinden katılarak kullanabilirsiniz .

Aynı şekilde aldığınız şey, A b cyeni bir b tüketen c-üreten "işlev" in yapamamasıdır. Ok, çeşitli ok birleştiricilerine katılarak veya belirli bir ok örneğinin ilkel işlemlerini kullanarak sizi tüketmekten bve yaratmamaktan koruyor c.

Örneğin, Yampa'daki sinyal işlevleri kabacadır (Time -> a) -> (Time -> b), ancak ek olarak belirli bir nedensellik sınırlamasına uymaları gerekir : zamandaki çıkış t, giriş sinyalinin geçmiş değerleri tarafından belirlenir: geleceğe bakamazsınız. Peki yaptıklarını yerine ile programlama olduğunu (Time -> a) -> (Time -> b)Birlikte programlamak, SF a bve ilkel dışarı sinyal fonksiyonlarını kurmak. Öyle olur ki SF a bbir işlev gibi davrandığından beri , ortak yapı "ok" denilen şeydir.


"Ok, çeşitli ok birleştiricilerine katılarak veya belirli bir ok örneğinin ilkel işlemlerini kullanarak sizi tüketmekten bve yaratmamaktan koruyor c." Bu eski cevabı cevaplamak için özür dilerim: bu cümle beni doğrusal türler hakkında düşündürdü, yani kaynaklar klonlanamıyor veya ortadan kaldırılamıyor. Herhangi bir bağlantı olabileceğini düşünüyor musunuz?
glaebhoerl

14

Programcının egzotik fonksiyon kompozisyonları yapmasını sağlamak için Monad ve Functor gibi okları düşünmeyi seviyorum.

Monad'lar veya Oklar (ve Functors) olmadan, işlevsel bir dilde işlevlerin bileşimi, bir işlevi başka bir işlevin sonucuna uygulamakla sınırlıdır. Monad'lar ve işlevlerle, iki işlevi tanımlayabilir ve daha sonra bu işlevlerin belirli bir monad bağlamında birbirleriyle ve kendilerine aktarılan verilerle nasıl etkileşime girdiğini belirten ayrı yeniden kullanılabilir kodlar yazabilirsiniz. Bu kod, Monad'ın bağlama kodunun içine yerleştirilir. Yani bir monad tek bir görünümdür, yeniden kullanılabilir ciltleme kodu için sadece bir kapsayıcıdır. İşlevler, bir monad bağlamında başka bir monaddan farklı olarak oluşur.

Basit bir örnek, eğer B işlevinde bir Belki monadında bir B işlevi varsa ve B bir Şey üretemiyorsa, Bind işlevi içinde kodun bulunduğu Belki monad'i gösterir. iki işlev, A'yı B'den gelen Hiçbir değere uygulamak için zahmete girmeden bir Hiçbiri çıkarır, eğer bir monad olmasaydı, programcının Nothing girişini test etmek için A'ya kod yazması gerekirdi.

Monad'ler ayrıca programcının her bir işlevin kaynak koduna gereksinim duyduğu parametreleri açıkça yazması gerekmediği anlamına gelir - bağlama işlevi parametre iletimini gerçekleştirir. Bu nedenle, monadları kullanarak, kaynak kodu, işlev A'nın "B" işlevini C ve D parametreleriyle "çağırıyor" gibi görünmek yerine, işlev isimlerinin statik bir zincir zinciri gibi görünmeye başlayabilir. hareketli makine - zorunlu olandan daha işlevsel.

Oklar aynı zamanda yeniden işlevsellik ve gizleme parametreleri sağlayan işlevleri bir bağlama işleviyle birleştirir. Ancak Oklar kendi aralarında bağlanabilir ve oluşturulabilir ve isteğe bağlı olarak çalışma zamanında verileri diğer Oklara yönlendirebilir. Artık verileri, verilere "farklı şeyler yapan" iki Ok yoluna uygulayabilir ve sonucu yeniden birleştirebilirsiniz. Veya verilerdeki değere bağlı olarak, hangi Okların dalını veri ileteceğini seçebilirsiniz. Sonuçta ortaya çıkan kod, anahtarlar, gecikmeler, entegrasyon vb. İle birlikte bir elektronik devre gibi. Program çok statik görünüyor ve devam eden verilerin manipülasyonunu görmemelisiniz. Düşünülmesi gereken daha az sayıda ve daha az parametre vardır ve hangi değerlerin hangi değerlerin alabileceği veya alınmayacağı hakkında daha az düşünmeniz gerekir.

Oklu bir program yazmak çoğunlukla, ayırıcılar, anahtarlar, gecikmeler ve birleştiriciler gibi rafların seçilmemesi, bu Oklara işlevleri kaldırma ve daha büyük Oklar oluşturmak için Okları birbirine bağlamayı içerir. Oklu Fonksiyonel Reaktif Programlama'da Oklar, programın son yinelemesinden elde edilen çıktıyla birleştirilen dünyadan gelen girdiyle birleştirilen, böylece çıkışın gerçek dünyadaki girdilere tepki verdiği bir döngü oluşturur.

Gerçek dünya değerlerinden biri zamandır. Yampa'da, Sinyal Fonksiyonu Oku, zaman parametresini bilgisayar programında görünmez bir şekilde gösterir - zamana asla erişemezsiniz, ancak programa bir bütünleştirici oku bağlarsanız, zaman geçtikten sonra kullanmak için kullanabileceğiniz zaman içinde tümleşik değerleri verir. diğer oklar.


ancak bu, uygulamalı bir fonksiyon gösterici gibi ses çıkarır (sarılı tipler için önceden var olan işlevleri yeniden kullanmak için, belirli bir bağlamda yardımcı işlevler sağlayan bir işlevin etrafındaki sarmalayıcı). Anlamak için kesinlikle daha fazla okumam gerekiyor, ama belki ne kaçırdığımı göstererek yardım edebilirsin
Belun

3

Sadece diğer cevaplara bir ek: Şahsen, bana böyle bir kavramın ne olduğunu (matematiksel olarak) ve bildiğim diğer kavramlarla nasıl ilişkili olduğunu anlamamda çok yardımcı oluyor.

Oklar durumunda, aşağıdaki yazıyı yararlı buldum - monadları, uygulayıcı işlevleri (deyimler) ve okları karşılaştırır: Deyimler habersiz, oklar titiz, monadlar Sam Lindley, Philip Wadler ve Jeremy Yallop tarafından teşvik ediliyor.

Ayrıca , bu konuyla ilgili olarak size bazı fikirler ve literatür sağlayabilecek hiç kimsenin bu bağlantıdan bahsetmediğine inanıyorum .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.