Здравствуйте, Sinclair, Вы писали:
S>Интересно. А при этом с "обычными", немонадными a и b такая запись работает? Ну, то есть можно ли вообще всегда описывать функции в do-нотации, чтобы они работали с произвольными монадами?
Чтоб такой код работал с обычными значениями, их придется обернуть в монаду Identity:
-- код был с ошибкой, правильно его записать так:
foo a b = do x <- a
y <- b
return $ x + y
-- или, что то же самое, но идиоматичнее:
foo = liftM2 (+)
-- теперь
runIdentity $ foo (Identity 2) (Identity 40)
-- получаем:
42
Это вполне применяется на практике, к примеру, все операции в пакете vector (это хаскельная библиотека для работы с массивами) монадические, а специализированная, нелифтнутые версии реализуются через монадические, вроде:
map f = mapM (return . f)
Lifted operators в хаскеле вполне реализуются:
{-# LANGUAGE FlexibleInstances, OverlappingInstances #-}
import Control.Applicative
instance (Applicative f, Num n) => Num (f n) where
(+) = liftA2 (+)
(-) = liftA2 (-)
(*) = liftA2 (*)
abs = fmap abs
signum = fmap signum
fromInteger = pure . fromIntegral
instance (Applicative f, Fractional n) => Fractional (f n) where
(/) = liftA2 (/)
recip = fmap recip
fromRational = pure . fromRational
Все, теперь у нас арифметика лифтнута в любой аппликативный функтор и мы можем писать на языке j:
>>> 2 + 7 * 8
58
>>> Just 2 + Just 7 * Just 8
Just 58
>>> Just 2 + Nothing * Just 8
Nothing
>>> [1..3] + [7..9] * [11,12]
[78,85,89,97,100,109,79,86,90,98,101,110,80,87,91,99,102,111]
>>> getZipList $ ZipList[1..3] + ZipList[7..9] * ZipList[11..13]
[78,98,120]
-- функции - это тоже функторы и монады:
>>> sum / (fromIntegral . length) $ [1..3] -- вычисляем среднее значение: делим сумму на длину
2.0
Вообще, нормальная работа с функторами/монадами в хаскеле возможна, в основном, не благодаря спецсинтаксису (который как раз страшноватый), а благодаря приличным возможностям для написания полиморфного кода и комбинирования комбинаторов
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll