JavaScript
- 35 ответов
- 0 вопросов
29
Вклад в тег
map
, применяющая функцию к каждому элементу массива. Без полиморфизма мы бы писали отдельную функцию для каждого типа:mapIntFloat :: (Int -> Float) -> [Int] -> [Float]
mapIntFloat f [] = []
mapIntFloat f (x:xs) = (f x) : (map f xs)
mapIntString :: (Int -> String) -> [Int] -> [String]
mapIntString f [] = []
mapIntString f (x:xs) = (f x) : (map f xs)
-- и так далее
mapTypeType
. Чтобы избежать повторения логики, параметризуем функцию map
относительно типов исходного массива и массива, получаемого в результате:map :: forall a b. (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = (f x) : (map f xs)
Int
или Float
у нас переменные типов: a
и b.map
для массивов, применима и к другим типам. Например, к optional-значениям. Без ad-hoc полиморфизма мы напишем что-то типа:mapList :: forall a b. (a -> b) -> [a] -> [b]
mapList f [] = []
mapList f (x:xs) = (f x) : (mapList f xs)
mapMaybe :: forall a b. (a -> b) -> Maybe a -> Maybe b
mapMaybe f Nothing = Nothing
mapMaybe f (Just x) = Just (f x)
class Functor f where
map :: (a -> b) -> f a -> f b
f
и теперь можем писать реализации для конкретных типов:instance Functor Maybe where
map f Nothing = Nothing
map f (Just x) = Just (f x)
instance Functor [] where
map f [] = []
map f (x:xs) = (f x) : (map f xs)
map
теперь имеет тип:map :: forall f a b. Functor f => (a -> b) -> f a -> f b
Functor
будет абстрактным классом с абстрактным методом map
, от которого наследуются типы Maybe
, List
и т.д. В таком случае сигнатура функции, принимающей и возвращающей функтор, будет выглядеть примерно так: foo :: Functor Int -> Functor String
.