Haskell - Функтор
Functorв 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]
Тогда в чем разница между map и fmap? Разница заключается в их использовании. Functor позволяет нам реализовать еще несколько функционалистов в различных типах данных, таких как «просто» и «ничего».
main = do
print (fmap (+7)(Just 10))
print (fmap (+7) Nothing)
Приведенный выше фрагмент кода даст следующий вывод на терминале:
Just 17
Nothing
Аппликативный функтор
Аппликативный функтор - это обычный функтор с некоторыми дополнительными функциями, предоставляемыми классом аппликативного типа.
Используя Functor, мы обычно сопоставляем существующую функцию с другой функцией, определенной внутри нее. Но нет никакого способа сопоставить функцию, которая определена внутри Functor, с другим Functor. Вот почему у нас есть еще один объект под названиемApplicative Functor. Эта возможность сопоставления реализуется классом Applicative Type, определенным вControlмодуль. Этот класс дает нам только два метода для работы: один -pure а другой <*>.
Ниже приводится определение класса Applicative Functor.
class (Functor f) => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
В соответствии с реализацией мы можем отобразить другой функтор двумя способами: "Pure" и "<*>". «Чистый» метод должен принимать значение любого типа и всегда будет возвращать аппликативный функтор этого значения.
В следующем примере показано, как работает аппликативный функтор -
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"
Моноиды
Все мы знаем, что Haskell определяет все в виде функций. В функциях у нас есть варианты получить наш ввод как вывод функции. Это то, чтоMonoid является.
А Monoid- это набор функций и операторов, вывод которых не зависит от ввода. Возьмем функцию (*) и целое число (1). Теперь, каким бы ни был вход, его выход останется только с тем же номером. То есть, если вы умножите число на 1, вы получите такое же число.
Вот определение моноида Type Class.
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} являются прекрасными примерами моноидов.