Haskell Prelude'a baktığımda bir işlev görüyorum const
:
const x _ = x
Bu işlevle ilgili hiçbir şey bulamıyorum.
Amaç ne? Bu işlevin nerede kullanılabileceğine dair bir örnek verebilir misiniz?
Haskell Prelude'a baktığımda bir işlev görüyorum const
:
const x _ = x
Bu işlevle ilgili hiçbir şey bulamıyorum.
Amaç ne? Bu işlevin nerede kullanılabileceğine dair bir örnek verebilir misiniz?
Yanıtlar:
Tüm esnekliklerine ihtiyacınız olmadığında daha yüksek dereceli işlevlere geçmek için kullanışlıdır. Örneğin, monadik sıra operatörü >>
, monadik bağlama operatörü açısından şu şekilde tanımlanabilir:
x >> y = x >>= const y
Lambda kullanmaktan biraz daha temiz
x >> y = x >>= \_ -> y
ve hatta anlamsız olarak kullanabilirsiniz
(>>) = (. const) . (>>=)
bu durumda özellikle tavsiye etmiyorum.
map (const 42) [1..5]
sonuçlanır [42, 42, 42, 42, 42]
.
const
tek bir bağımsız değişkenin gerekli olduğu bir işlevi ('a iletme gibi map
) elde etmek için kullanışlıdır .
head = foldr const (error "Prelude.head: empty list")
Hammar en mükemmel doğrudan cevap eklemek için: mütevazi fonksiyonları gibi const
ve id
bunlar aynı nedenden dolayı yüksek mertebeden fonksiyonu olarak gerçekten yararlı olan temel yılında KAYAK combinator hesabının .
Haskell'in başlangıç işlevlerinin bilinçli olarak bu biçimsel sistem veya herhangi bir şeyden sonra modellendiğini düşünmüyorum. Haskell'de zengin soyutlamalar yaratmak çok kolaydır, bu nedenle bu tür teorik şeylerin pratik olarak yararlı olduğunu sıklıkla görürsünüz.
Utanmaz fiş, ancak Applicative örneğinin (->)
aslında buradaS
ve K
birleştiriciler olduğu hakkında blog yazdım , eğer ilgilendiğiniz türden bir şeyse.
((->) e)
aynı zamanda okuyucu monad - Reader
ve benzeri sadece newtype
sarmalayıcıdır - ve o zaman ask
işlev id
, yani I
birleştirici de budur. Eğer Haskell Curry orijinal BCKW temelinde de yerine bakacak olursak, B
, K
ve W
vardır fmap
, return
ve join
sırasıyla.
Bu işlevle ilgili hiçbir şey bulamıyorum.
Diğer cevapların birçoğu ile ilgili görece ezoterik (en azından yeni gelen için) uygulamaları tartışıyor const
. İşte basit bir tane: const
iki argüman alan, birincisini atan ancak ikinciyle ilginç bir şey yapan bir lambdadan kurtulmak için kullanabilirsiniz .
Örneğin, aşağıdaki (verimsiz ama öğretici) uygulama length
,
length' = foldr (\_ acc -> 1 + acc) 0
olarak yeniden yazılabilir
length' = foldr (const (1+)) 0
bu belki daha zariftir.
İfade const (1+)
aslında anlamsal olarak eşdeğerdir \_ acc -> 1 + acc
, çünkü bir argüman alır, onu atar ve bölümü döndürür (1+)
.
Kullanmak için basit bir örnek const
olup Data.Functor.(<$)
. Bu işlevle şunu söyleyebilirsiniz: Burada sıkıcı bir şey olan bir işlevim var, ama bunun yerine, işlevin şeklini değiştirmeden içinde başka bir ilginç şey olmasını istiyorum. Örneğin
import Data.Functor
42 <$ Just "boring"
--> Just 42
42 <$ Nothing
--> Nothing
"cool" <$ ["nonsense","stupid","uninteresting"]
--> ["cool","cool","cool"]
Tanım şu şekildedir:
(<$) :: a -> f b -> f a
(<$) = fmap . const
veya anlamsız olarak yazılmamış:
cool <$ uncool = fmap (const cool) uncool
const
Burada girdiyi "unutmak" için nasıl kullanıldığını görüyorsunuz .
Diğer bir kullanım, değerlendirilmemesi gereken (belirsiz türleri çözmek için kullanılan) bir kukla bağımsız değişkeni olan sınıf üyesi işlevleri uygulamaktır. Data.bits içinde olabilecek örnek:
instance Bits Int where
isSigned = const True
bitSize = const wordSize
...
Const kullanarak, sabit değerler tanımladığımızı açıkça söylüyoruz.
Şahsen ben kukla parametrelerin kullanımından hoşlanmıyorum, ancak bir sınıfta kullanılıyorsa, bu örnek yazmanın oldukça güzel bir yoludur.
const
sadece diğer işlevlerle birlikte aradığınız uygulama olabilir. İşte keşfettiğim bir örnek.
Diyelim ki 2-demetlik bir yapıyı başka bir 2-demet yapıya yeniden yazmak istiyoruz. Bunu şu şekilde ifade edebilirim:
((a,b),(c,d)) ⇒ (a,(c,(5,a)))
Örüntü eşleme ile basit bir tanım verebilirim:
f ((a,b),(c,d)) = (a,(c,(5,a)))
Ya bu tür yeniden yazmalar için anlamsız (zımni) bir çözüm istersem? Bazıları daha sonra düşünür ve uğraşır, cevap, herhangi bir yeniden yazımı ifade edebileceğimizdir (&&&), const, (.), fst, snd
. (&&&)
Kimden olduğuna dikkat edin Control.Arrow
.
Bu fonksiyonları kullanan örneğin çözümü:
(fst.fst &&& (fst.snd &&& (const 5 &&& fst.fst)))
İle benzerliğe dikkat edin (a,(c,(5,a)))
. Ya &&&
ile değiştirirsek ,
? Sonra okur:
(fst.fst, (fst.snd, (const 5, fst.fst)))
Dikkat edin a
, ilk unsurun ilk unsuru ve fst.fst
projelendirme budur. Dikkat edin c
, ikinci unsurun ilk unsuru nasıldır ve fst.snd
projelendirme budur. Yani değişkenler, kaynaklarına giden yol haline gelir.
const
sabitleri tanıtmamıza izin verir. İsmin anlamla uyuşması ilginç!
Eğer bir anlamsız bir tarzda herhangi bir işlev yazabilirsiniz böylece Sonra (çok uzun gibi işlevler gibi vaka analizi mevcut olduğu gibi uygulamalı ile bu fikri genelleştirilmiş maybe
, either
, bool
). Yine, const
sabitleri tanıtma rolünü oynar. Bu çalışmayı Data.Function.Tacit paketinde görebilirsiniz.
Soyut olarak, hedefe başladığınızda ve sonra bir uygulamaya doğru çalıştığınızda, cevaplar sizi şaşırtabilir. Yani, herhangi bir işlev, bir makinedeki herhangi bir dişli kadar gizemli olabilir. Bununla birlikte, tüm makineyi ortaya çıkarmak için geri çekerseniz, o çarkın gerekli olduğu bağlamı anlayabilirsiniz.
Nothings
Bir dizenin uzunluğuna eşit bir liste oluşturmak istediğinizi varsayalım. Gibi const
döner ilk argüman, hiçbir saniyesini önemi, yapabileceğiniz:
listOfNothings :: String -> [Maybe Char]
listOfNothings = (map . const) Nothing
veya daha açık bir şekilde:
listOfNothing st = map (const Nothing) st
Bir listeyi döndürmek istediğinizi söyleyin. Bu, Haskell'de bunu yapmanın deyimsel bir yoludur:
rotate :: Int -> [a] -> [a]
rotate _ [] = []
rotate n xs = zipWith const (drop n (cycle xs)) xs
Bu işlev, iki diziyi işlevle sıkıştırır const
; ilki sonsuz döngüsel dizidir, ikincisi ise başladığınız dizidir.
const
sınır kontrolü görevi görür ve döngüsel diziyi sonlandırmak için orijinal diziyi kullanır.
Bakınız: Haskell'de bir listeyi döndürme
Bu işlevle ilgili hiçbir şey bulamıyorum.
Verilen bir listenin tüm alt dizilerini oluşturmak istediğinizi varsayalım.
Her liste öğesi için, belirli bir noktada Doğru (mevcut alt diziye dahil edin) veya Yanlış (dahil etmeyin) seçenekleriniz vardır. Bu, filterM işlevi kullanılarak yapılabilir .
Bunun gibi:
λ> import Control.Monad
λ> :t filterM
filterM :: Applicative m => (a -> m Bool) -> [a] -> m [a]
λ>
Örneğin, tüm alt dizilerini istiyoruz [1..4]
.
λ> filterM (const [True, False]) [1..4]
[[1,2,3,4],[1,2,3],[1,2,4],[1,2],[1,3,4],[1,3],[1,4],[1],[2,3,4],[2,3],[2,4],[2],[3,4],[3],[4],[]]
λ>
backgroundColor :: Text -> Color
benim içinbackgroundColor = const White