Функтор в Haskell является своего рода функциональным представлением различных типов, которые можно отобразить. Это концепция высокого уровня реализации полиморфизма. По словам разработчиков Haskell, все типы, такие как List, Map, Tree и т. Д., Являются экземпляром Haskell Functor.
Functor — это встроенный класс с определением функции, подобным —
class Functor f where fmap :: (a -> b) -> f a -> f b
Исходя из этого определения, мы можем заключить, что Functor является функцией, которая принимает функцию, скажем, fmap () и возвращает другую функцию. В приведенном выше примере fmap () является обобщенным представлением функции map () .
В следующем примере мы увидим, как работает Haskell Functor.
main = do print(map (subtract 1) [2,4,8,16]) print(fmap (subtract 1) [2,4,8,16])
Здесь мы использовали и map (), и fmap () над списком для операции вычитания. Вы можете заметить, что оба оператора приведут к одному и тому же результату списка, содержащего элементы [1,3,7,15].
Обе функции вызвали другую функцию subtract (), чтобы получить результат.
[1,3,7,15] [1,3,7,15]
Тогда в чем разница между картой и fmap? Разница заключается в их использовании. Functor позволяет нам реализовать еще несколько функционалистов в разных типах данных, таких как «просто» и «ничего».
main = do print (fmap (+7)(Just 10)) print (fmap (+7) Nothing)
Приведенный выше фрагмент кода выдаст следующий вывод на терминал —
Just 17 Nothing
Аппликативный Функтор
Аппликативный функтор — это обычный функтор с некоторыми дополнительными функциями, предоставляемыми классом Applicative Type.
Используя Functor, мы обычно отображаем существующую функцию с другой функцией, определенной внутри нее. Но нет никакого способа сопоставить функцию, которая определена внутри Функтора, с другим Функтором. Вот почему у нас есть еще одно средство под названием Applicative Functor . Это средство отображения реализуется классом Applicative Type, определенным в модуле Control . Этот класс дает нам только два метода для работы: один — чистый, а другой — <*> .
Ниже приведено определение класса аппликативного функтора.
class (Functor f) => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b
В соответствии с реализацией мы можем отобразить другой Functor, используя два метода: «Pure» и «<*>» . Метод «Pure» должен принимать значение любого типа, и он всегда будет возвращать Applicative Functor этого значения.
В следующем примере показано, как работает Applicative Functor:
import Control.Applicative f1:: Int -> Int -> Int f1 x y = 2*x+y main = do print(show $ f1 <$> (Just 1) <*> (Just 2) )
Здесь мы реализовали аппликативные функторы в вызове функции f1 . Наша программа даст следующий результат.
"Just 4"
Моноиды
Мы все знаем, что Хаскелл определяет все в форме функций. В функциях у нас есть опции для получения нашего ввода в качестве выхода функции. Вот что такое моноид .
Monoid — это набор функций и операторов, в которых выходные данные не зависят от его входных данных. Давайте возьмем функцию (*) и целое число (1). Теперь, каким бы ни был ввод, его вывод останется только тем же номером. То есть, если вы умножите число на 1, вы получите тот же номер.
Вот определение класса класса моноида.
class Monoid m where mempty :: m mappend :: m -> m -> m mconcat :: [m] -> m mconcat = foldr mappend mempty
Посмотрите на следующий пример, чтобы понять использование Monoid в Haskell.
multi:: Int->Int multi x = x * 1 add :: Int->Int add x = x + 0 main = do print(multi 9) print (add 7)
Наш код выдаст следующий результат:
9 7
Здесь функция «multi» умножает ввод на «1». Точно так же функция «добавить» добавляет ввод с «0». В обоих случаях вывод будет таким же, как и ввод. Следовательно, функции {(*), 1} и {(+), 0} являются прекрасными примерами моноидов.