Перед Haskell 98 были Haskell с 1.0 по 1.4. Очень интересно видеть развитие на протяжении многих лет, поскольку функции были добавлены к ранним версиям стандартизованного Haskell.Почему стандартные классы Haskell 98 были уступают Haskell 1.3?
Например, стандартизованная нотация была стандартизована Haskell 1.3 (опубликовано в 1996-05-01). В Prelude
, мы находим следующие определения (стр 87):
-- Monadic classes
class Functor f where
map :: (a -> b) -> f a -> f b
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
(>>) :: m a -> m b -> m b
return :: a -> m a
m >> k = m >>= \_ -> k
class (Monad m) => MonadZero m where
zero :: m a
class (MonadZero m) => MonadPlus m where
(++) :: m a -> m a -> m a
же определения встречаются в Haskell 1.4. У меня есть несколько проблем с этим (например, MonadPlus
reform еще не произошло), но в целом это очень хорошее определение.
Это очень отличается от Haskell 98, где находится следующее определение:
-- Monadic classes
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
(>>) :: m a -> m b -> m b
return :: a -> m a
fail :: String -> m a
-- Minimal complete definition:
-- (>>=), return
m >> k = m >>= \_ -> k
fail s = error s
Это также определение в Haskell 2010. У меня есть следующие проблемы с этим определением:
MonadZero
иMonadPlus
ушли. Это были полезные классы.В случае выхода из строя матча шаблон в сделай нотации ...
- Haskell 1.3 использует
zero
. Закон левого нуля применяется (zero >>= k = zero
), поэтому вы знаете, что должно произойти. - Haskell 98 использует
fail msg
, гдеmsg
является компилятором в случае GHC. Все может случиться, никаких гарантий относительно его семантики. Таким образом, это не большая функция для пользователей. Как следствие, поведение неудачных совпадений шаблонов в заявке Haskell 98 непредсказуемо!
- Haskell 1.3 использует
Имена являются менее общими (например, по сравнению с
map
fmap
). Не большая проблема, но это мой колючий глаз.
В целом, я думаю, что эти изменения не были к лучшему. На самом деле, я думаю, что они были шагом назад от Haskell 1.4. Почему эти вещи изменились для Haskell 98 и почему так?
Как в стороне, я могу представить следующие защиты:
- "
fail
позволяет для обнаружения ошибок." Только для программистов и только во время работы. Сообщение об ошибке (unportable!) - это не то, что вы хотите проанализировать. Если вы действительно заботитесь об этом, вы должны отслеживать это явно. Теперь у нас естьControl.Failure
из пакетаfailure
, который делает намного лучше работу (failure x
ведет себя в основном какzero
). - «Слишком много классов делает разработку и использует слишком много». Слишком мало классов нарушает их законы, и эти законы так же важны, как и типы.
- «Функции с ограниченным доступом легче изучить». Тогда почему же нет
SimplePrelude
, а большинство классов удалено? Это всего лишь одна магическая декларация для студентов, они могут так много управлять. (Возможно, тоже{-# LANGUAGE RebindableSyntax #-}
, но опять же, студенты очень хорошо при копировании.) - «Ограниченные экземпляром функции делают ошибки более читабельными». Я использую
fmap
гораздо чаще, чемmap
, так почему бы неmap
иlistMap
вместо этого?
Одна из причин, по которой «карта» переименована в «fmap» и «map», специализирующаяся на списки, заключается в том, что сообщения об ошибках, которые вы получаете при сопоставлении списков, гораздо более дружелюбны для новичков. Представьте, что вы новичок в Haskell (или вообще программировании) и просто хотите изменить значения в списке, и вы получите сообщение об ошибке «No instance for (Functor f0)»! – kqr
Я думал, что я опроверг это в своем ответе, дважды: новички могли использовать 'SimplePrelude' (имея' map = listMap'), более продвинутые пользователи могли бы использовать 'listMap' вместо' map'. –
Я просто хотел указать на него новичка, поскольку вы не упомянули об этом конкретно. Проблема с вашими предложениями в том, что они делают экспертов демографическими, которые, вероятно, будут знать о дружелюбной с новичком стороне Haskell, и новички будут пытаться понять экспертную сторону по умолчанию Haskell - совершенно противоположное тому, что нужно в простой в освоении язык!Обратное к тому, что вы предлагаете, уже существует в форме [basic-prelude] (http://hackage.haskell.org/packages/archive/basic-prelude/0.3.6.0/doc/html/BasicPrelude.html). – kqr