Just [1]
ve Just [2]
'dan Just [1, 2]
'a giden Haskell'de neyin açık bir şekilde görülmesi gerektiğini yapmaya çalışıyorum. Ancak, alakalı ancak yararsız sayfalar bulmaya devam ederken çevrimiçi olarak hiçbir şey bulamıyorum. Peki bunu nasıl başarabilirsin?Haskell'de Birleştirme/Ekleme
cevap
Sen liftA2 (++)
kullanabilirsiniz:
liftA2 (++) :: Maybe [a] -> Maybe [a] -> Maybe [a]
liftA2
Applicative
bir ikili işlevini kaldırır.
Applicative
s, bir bağlamdaki keyfi argümanların işlevlerini kaldırmak için tasarlanmıştır, bu nedenle bunlar için mükemmeldir. Bu durumda,
Applicative
kullanıyoruz
Maybe
. Bunun nasıl çalıştığını görmek için, tanım bakabilirsiniz:
(a -> b) -> f a -> f b
:
liftA2 :: (Applicative f) => (a -> b -> c) -> f a -> f b -> f c
liftA2 f a b = f <$> a <*> b
(<$>)
sadece f
içindeki bir işletim saf değerler üzerine herhangi bir işlev kaldırır. (Eğer Functor
s aşina eğer, fmap
için sadece bir takma ad.) Maybe
için:
_ <$> Nothing = Nothing
f <$> Just x = Just (f x)
(<*>)
biraz daha zordur: bu f
içinde bir değere f
içinde bir işlev geçerlidir: f (a -> b) -> f a -> f b
. Maybe
için:
Just f <*> Just x = Just (f x)
_ <*> _ = Nothing
(Aslında, f <$> x
Maybe
için Just f <*> x
olduğu pure f <*> x
aynı şey söz konusudur.) Yani
, biz liftA2 (++)
tanımını genişletebilirsiniz:
liftA2 (++) a b = (++) <$> a <*> b
-- expand (<$>)
liftA2 (++) (Just xs) b = Just (xs ++) <*> b
liftA2 (++) _ _ = Nothing
-- expand (<*>)
liftA2 (++) (Just xs) (Just ys) = Just (xs ++ ys)
liftA2 (++) _ _ = Nothing
Gerçekten de, herhangi bir argüman sayısını herhangi bir Applicative
, j'ye yükseltmek için bu operatörleri kullanabiliriz. liftA2
modelini takip ederek. Bu uygulama stili olarak adlandırılır ve deyimsel Haskell kodunda çok yaygındır. Bu durumda, a
ve b
zaten değişkenler ise, (++) <$> a <*> b
yazarak doğrudan kullanmak için daha deyimsel olabilir. (Diğer yandan, kısmen uyguluyorsanız - Daha yüksek dereceden işlevine geçmek demek - o liftA2 (++)
tercih edilir.) Hiç çalışırken kendinizi bulmak eğer öyleyse
Her Monad
, bir Applicative
olduğunu Bir işlevi bir bağlamda "kaldır", Applicative
muhtemelen sizin aradığınız şeydir. @ Ehird cevabı büyük ise
, ben formda bir noobish çözümü kullanılmış olurdu: şunu kullanabilirsiniz
mergeJust a b = do
a' <- a
b' <- b
return (a' ++ b')
+1 bile noobs, bu sorunu çözebilir. Aynı zamanda bir monad anlama olarak da yazabilirsiniz: '[a '++ b' | Bir '<- a, b' <- b] ' –
Just
s listesine çözüm genişletmek için
fmap join $ sequence [Just[1],Just[2],Just[3]]
-- Just [1,2,3]
Diğer çözümlerde bahsedilmediğinden, burada söyleyeceğim. Görevin yerine getirilmesinin en kolay yolu, bence, Data.Monoid
'dan <>
(veya mappend
) kullanmaktır.
import Data.Monoid
Just [1,2] <> Just [7,8] == Just [1,2,7,8]
Ancak unutmayın ehird en uygulamalı çözümü aksine bu çözüm, Nothing
değerlerine kısa devre olacak.
Just [1,2] <> Nothing ---> Just [1,2]
--However
(++) <$> Just [1,2] <*> Nothing ---> Nothing
Bazen bu bazen uygun davranış olmayabilir. –
Awesome :) Teşekkürler, beni saçlarımı yırtarak kurtardın. [2] 've' Sadece [3] '-' '[2, 3] için bir eşdeğer olduğunu bilemez misiniz? :) –
@DeanBarnes: '(2 :) <$> Sadece [3]' –
Fantastik cevap, teşekkürler @ehird! Bu temelde şu andan itibaren referansım :) –