Подтвердить что ты не робот

Является ли Haskell разработанным для поощрения венгерской нотации?

Я изучаю Haskell и начал замечать общие суффиксы в таких функциях, как:

debugM
mapM_
mapCE

который известен как венгерская нотация. Но в то же время я могу использовать классы типов для написания недвусмысленного кода, например:

show
return

Поскольку такие функции, как map, являются настолько распространенными и используются во многих контекстах, почему бы не позволить контролеру типа выбрать правильную полиморфную версию map, fmap, mapM, mapM_ или mapCE?

4b9b3361

Ответ 1

Там немного "венгерской нотации", но это совсем другое. Короче говоря, система типа Haskell устраняет необходимость в большей части.

Элемент map/mapM является аккуратным примером. Эти две функции придают точно такое же понятие, но не могут быть представлены в виде полиморфизма, потому что абстрагирование от разницы было бы действительно шумным. Поэтому мы выбираем венгерскую нотацию.

Чтобы быть ясным, два типа:

map  ::            (a ->   b) -> ([a] ->   [b])
mapM :: Monad m => (a -> m b) -> ([a] -> m [b])

Они выглядят одинаково, все mapM это добавляет монаду, но не то же самое. Структура раскрывается, когда вы делаете следующие синонимы

type Arr    a b = a ->   b
type Klei m a b = a -> m b

и перепишите типы как

map  ::            Arr    a b -> Arr    [a] [b]
mapM :: Monad m => Klei m a b -> Klei m [a] [b]

Следует отметить, что Arr и Monad m => Klei m часто являются очень похожими вещами. Оба они образуют определенную структуру, известную как "категория", которая позволяет нам поднимать все виды вычислений внутри нее. [0]

Нам хотелось бы абстрагироваться от выбора категории с чем-то вроде

class Mapping cat where
  map :: cat a b -> cat [a] [b]

instance            Mapping (->)     where map = Prelude.map
instance Monad m => Mapping (Klei m) where map = mapM         -- in spirit anyway

но оказывается, что еще больше можно получить путем абстрагирования над частью списка с помощью Functor [1]

class Functor f where
  map :: (a -> b) -> (f a -> f b)

instance Functor [] where
  map = Prelude.map

instance Functor Maybe where
  map Nothing  = Nothing
  map (Just a) = Just (f a)

и поэтому для простоты мы используем венгерскую нотацию, чтобы сделать разницу в категории, вместо того, чтобы перевернуть ее в функциональность полиморфизма Haskell.

[0] Примечательно, что тот факт, что Klei m является категорией, означает, что m является монадой, а законы категории становятся точно монадами. В частности, это мой любимый способ запомнить, что такое законы монады.

[1] Технически единственный метод Functor называется fmap not map, но его можно и, возможно, следовало назвать просто map. Добавлен f, так что сигнатура типа для map остается простой (специализированной по спискам) и, таким образом, менее запутанна для новичков. Было ли это правильным решением, это дискуссия, которая продолжается и сегодня.

Ответ 2

Ваше предположение состоит в том, что все они делают примерно одно и то же - они этого не делают. map и fmap - почти такая же функция - map - это просто fmap, специализированный на функторе [] (по историческим причинам или так, что новички будут получать менее запутывающие ошибки типа - я не уверен).

mapM и mapM_, с другой стороны, похожи на map, за которыми следуют sequence или sequence_ соответственно - в то время как то, что они делают, может выглядеть связанным, они делают разные вещи. Кстати, функция, которая ведет себя как fmap для монадов,... fmap (которая по историческим причинам также сшита с помощью специализированной сигнатуры liftM), поскольку Monad по определению также Functor s; обратите внимание, что это прямо сейчас, не соблюдается стандартной библиотекой - исторический надзор, который должен быть исправлен с помощью GHC 7.10, если я не ошибаюсь.

Я не знаю, что вам сказать о debugM и mapCE, поскольку я не видел их раньше.