Türleri karşılaştırırsak
(<*>) :: Applicative a => a (s -> t) -> a s -> a t
(>>=) :: Monad m => m s -> (s -> m t) -> m t
iki kavramı ayıran şeyin ne olduğuna dair bir ipucu elde ederiz. Bu (s -> m t)
tipinde (>>=)
bir değer gösterdiği s
bir hesaplama davranışını belirler m t
. Monadlar, değer ve hesaplama katmanları arasında girişime izin verir. (<*>)
Operatör böyle müdahaleyi sağlar: fonksiyonu ve argüman hesaplamaları değerlere bağlı olmayan. Bu gerçekten ısırıyor. Karşılaştırmak
miffy :: Monad m => m Bool -> m x -> m x -> m x
miffy mb mt mf = do
b <- mb
if b then mt else mf
iki hesaplama arasında karar vermek için bazı etkilerin sonucunu kullanır (örneğin füzeleri fırlatmak ve bir ateşkes imzalamak), oysa
iffy :: Applicative a => a Bool -> a x -> a x -> a x
iffy ab at af = pure cond <*> ab <*> at <*> af where
cond b t f = if b then t else f
ki değerini kullanır ab
arasında seçim yapmak için değerleri iki hesaplamalar at
ve af
belki de trajik etkisine, hem de elde edildiğini.
Monadik versiyon, esasen (>>=)
bir değerden bir hesaplama seçmenin ekstra gücüne dayanır ve bu önemli olabilir. Bununla birlikte, bu gücü desteklemek, monadların bestelenmesini zorlaştırır. 'Double-bind' oluşturmaya çalışırsak
(>>>>==) :: (Monad m, Monad n) => m (n s) -> (s -> m (n t)) -> m (n t)
mns >>>>== f = mns >>-{-m-} \ ns -> let nmnt = ns >>= (return . f) in ???
bu kadar uzağa gidiyoruz, ama şimdi katmanlarımız karmakarışık. Elimizde bir tane var n (m (n t))
, bu yüzden dışardan kurtulmamız gerekiyor n
. Alexandre C'nin dediği gibi, uygun bir
swap :: n (m t) -> m (n t)
sırasını değiştirmek amacıyla n
içeriye ve join
diğer bunu n
.
Daha zayıf 'çift uygulama' tanımlaması çok daha kolaydır
(<<**>>) :: (Applicative a, Applicative b) => a (b (s -> t)) -> a (b s) -> a (b t)
abf <<**>> abs = pure (<*>) <*> abf <*> abs
çünkü katmanlar arasında hiçbir girişim yoktur.
Buna karşılık, Monad
s'nin ekstra gücüne gerçekten ne zaman ihtiyacınız olduğunu ve Applicative
destekleyen katı hesaplama yapısından ne zaman kurtulabileceğinizi anlamak iyidir .
Bu arada, monadları oluşturmak zor olsa da, ihtiyacınız olandan daha fazlası olabileceğini unutmayın. Türü m (n v)
ile işlem gösterir m
daha sonra işlem, -Etkileri n
a -Etkileri v
-değeri, m
daha önce -Etkileri bitiş n
-Etkileri (dolayısıyla gerek başlangıç swap
). m
-Efektleri -etkileri ile birleştirmek istiyorsanız n
, o zaman kompozisyon sorulamayacak kadar fazla olabilir!