2012-01-18 14 views
7

Jak ściśle składa się monada? Data.Foldable ma ścisły kod foldl' i monadyczny foldlM, ale nie ma ścisłej definicji foldlM'? Czy surowość jest w jakiś sposób zdefiniowana przez samą monadę? Jeśli tak, to w jaki sposób można ustalić, co to jest?Czy Haskell ma foldlM?

Wyobraź sobie, że muszę ustalić, czy iloczyn olbrzymiej listy elementów pierścienia wynosi zero, ale mój pierścień nie jest domeną integralną, tj. Zawiera zero wzorca. W takim przypadku powinienem przekierować rekurencyjnie foldl moje mnożenie *** nad listą, ale zwracam False w momencie, gdy produkt stanie się zero, zamiast czekać na pełny produkt.

safelist :: [p] -> Bool 
safelist [] = True 
safelist (x:xs) = snd $ foldl' f (x,True) xs 
    where f (u,b) v = (w, b && w /= Zero) where w = u *** v 

I być może nieco uprościć ten kod za pomocą Maybe monada na foldlM ale robi tak pozornie brakuje wymaganej surowości.

Odpowiedz

8

Nie ma takich standardowych funkcji, ale to jest łatwe do zdefiniowania:

foldM' :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m a 
foldM' _ z [] = return z 
foldM' f z (x:xs) = do 
    z' <- f z x 
    z' `seq` foldM' f z' xs 

To jest po prostu średnia foldM, ale z tym samym seq ing w nim, że foldl' ma (w porównaniu do foldl). Prawdopodobnie nie jest on zdefiniowany nigdzie standardowo, ponieważ prawdopodobnie nie będzie aż tak użyteczny: w przypadku większości monad, (>>=) jest "ścisły" w tym sensie, że musisz użyć lewego fałdu bez przepełnienia stosu; Jest to użyteczne tylko wtedy, gdy nadmierne uderzenia znajdują się w samych wartościach zwracanych, ale przydatna aplikacja o numerze foldM wykona pewne monadyczne obliczenia z wartością z ostatniego kroku, co spowoduje, że będzie to mało prawdopodobne.

Myślę, że twój kod jest wystarczająco prosty, jak jest; Wątpię, czy foldM' uczyniłoby to bardziej eleganckim.

+0

Ahh, przypuszczam, że monada mogłaby robić rzeczy ścisłe, jeśli miałaby w sobie ostre flagi, ale nie inaczej. I nie robią tego żadne standardowe monady. Dzięki! –

+3

@JeffBurdges - oto rodzaj obserwacji ad-hoc, której Monadyczne '> =' są ścisłe vs leniwy: http://stackoverflow.com/a/8250334/208257 –

+0

Rzeczywiście, wątpię, że 'foldM'' pomoże, jeśli twoje '(>> =)' jest zbyt leniwe, ponieważ np wymuszenie wartości zwróconej przez leniwą Monadę 'State' niekoniecznie wymusza stan. – ehird