Bir deseni yüklem işlevi olarak kullanmanın uygun bir yolu var mı?


10

Son zamanlarda, bir yüklem işlevini başka bir işleve geçirmem gereken durumlarda çalışıyorum ve sık sık aradığım mantık aslında "bu değer bu modelle eşleşiyor mu?"

Desen eşleştirme, bildirimlerde, dobloklarda ve liste kavrayışlarında tercih edilir gibi görünür , ancak bir a -> Boolşekilde bir desende geçmenin çok kullanışlı olacağı bir yüklem alan bir dizi işlev vardır . Örneğin takeWhile, until, find, span, vs.

Şimdiye kadar yapıyorum \a -> case a of MyCons _ -> True; otherwise -> Falseya da adlandırılmış bir işlev la yazıyorum let myPred (MyCons _) = True; myPred _ = False inama ikisi de çok çirkin görünüyor ve çok deyimsel değil. "Açık" (ve yanlış) yol böyle bir şey olurdu, \(MyCons _) -> Trueancak bu doğal olarak kısmi olduğu için bir hata atıyor ve o zaman bile daha temiz bir yol olmalı gibi geliyor.

Bu tür şeyleri yapmanın daha özlü / temiz bir yolu var mı? Yoksa tamamen yanlış bir şekilde mi gideceğim?


1
Belki de bu "kişisel tat" bir şeydir, ancak bu yüklemi tek bir yerde ihtiyacınız varsa, letsevmediğiniz maddeden oldukça memnun olurum - eşdeğer wheremaddeyi tercih etsem de, bu da ana tanımı karıştırmaz. Tabii ki bu yardımcı programa bir kereden fazla ihtiyaç duyuyorsanız, üst düzey bir işlev olarak tanımlayabilirsiniz.
Robin Zigmond

Kesinlikle iyi çalışıyor. Sorum, Haskell'in tipik olarak ne kadar etkileyici özü ile biraz motive oldu. Genellikle deyimsel Haskell'in çok az fikir yinelemesi varmış gibi hissettirir ve kabartmayı en aza indirir. Bu yüzden let myPred...stilin kötü olduğunu düşünüyorum bile değil , ama çok basit bir fikir beklediğimden çok daha ayrıntılı hissediyorum, bu da yanlış ağaca havlayıp havlamadığımı merak etmemi sağlıyor.
David Sampson

2
Prizmalara (objektiften) bir göz atabilirsiniz. Birinci sınıf
kompostlanabilir

1
Bu tür bir üst düzey işlevi nerede kullandığınıza dair bir örnek görmemiz gerektiğini düşünüyorum. Bir parçam, sorunun ilk etapta böyle bir yüklem gerektiren tasarımda olduğunu söylemek istiyor.
chepner

bunun için Haskell98 yolu, veri türünüz için büyük / küçük harf eşleştirme (dekonstrüktif) işlevini tanımlamaktır maybe :: b -> (a -> b) -> Maybe a -> bve bool :: a -> a -> Bool -> adaha sonra bunu Boolean üreten işlev (ler) ile bağımsız değişken olarak kullanmaktır. örneğin myCons z f (MyCons x) = f x ; myCons z f _ = z, arayın myCons False (const True) aMyConsValue. Bu neredeyse yazdığınız şeydir, sadece içine konulmuş işlevsel argüman (lar) aracılığıyla bir "dolaylılık" / "soyutlama" düzeyi daha vardır.
Ness

Yanıtlar:


7

Kullanmak için Dil Uzantısı LambdaCase kullanabilirsiniz \case MyCons _ -> True; _ -> False, ancak bu o kadar fazla karakter kaydetmez.

Sana fonksiyonları bir dizi yazabilirsiniz inanıyoruz constructedWith :: (Generic a) => (b -> a) -> a -> Bool, constructedWith2 :: (Generic a) => (b -> c -> a) -> a -> Boolama birkaç saat şeyleri test etmeden bunu uygulamak için Generics ile yetkili yeterli değilim. Bunu deneyeceğim ve eğer çözebilirsem ya da çıkmazsa cevabımı düzenleyeceğim.

EDIT: Evet, yapabilirsin! Kodumu sıfırdan uygulayan bir link:

https://repl.it/@lalaithion/ConstructedWith

Ancak, tüm genel kod bağlantıları için http://hackage.haskell.org/package/generic-deriving-1.13.1/docs/Generics-Deriving-ConNames.html gibi bir şey kullanmak daha iyi olabilir.

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.