2013-09-12 1 views
29

Перед 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 непредсказуемо!
  • Имена являются менее общими (например, по сравнению с mapfmap). Не большая проблема, но это мой колючий глаз.


В целом, я думаю, что эти изменения не были к лучшему. На самом деле, я думаю, что они были шагом назад от Haskell 1.4. Почему эти вещи изменились для Haskell 98 и почему так?


Как в стороне, я могу представить следующие защиты:

  • "fail позволяет для обнаружения ошибок." Только для программистов и только во время работы. Сообщение об ошибке (unportable!) - это не то, что вы хотите проанализировать. Если вы действительно заботитесь об этом, вы должны отслеживать это явно. Теперь у нас есть Control.Failure из пакета failure, который делает намного лучше работу (failure x ведет себя в основном как zero).
  • «Слишком много классов делает разработку и использует слишком много». Слишком мало классов нарушает их законы, и эти законы так же важны, как и типы.
  • «Функции с ограниченным доступом легче изучить». Тогда почему же нет SimplePrelude, а большинство классов удалено? Это всего лишь одна магическая декларация для студентов, они могут так много управлять. (Возможно, тоже {-# LANGUAGE RebindableSyntax #-}, но опять же, студенты очень хорошо при копировании.)
  • «Ограниченные экземпляром функции делают ошибки более читабельными». Я использую fmap гораздо чаще, чем map, так почему бы не map и listMap вместо этого?
+0

Одна из причин, по которой «карта» переименована в «fmap» и «map», специализирующаяся на списки, заключается в том, что сообщения об ошибках, которые вы получаете при сопоставлении списков, гораздо более дружелюбны для новичков. Представьте, что вы новичок в Haskell (или вообще программировании) и просто хотите изменить значения в списке, и вы получите сообщение об ошибке «No instance for (Functor f0)»! – kqr

+2

Я думал, что я опроверг это в своем ответе, дважды: новички могли использовать 'SimplePrelude' (имея' map = listMap'), более продвинутые пользователи могли бы использовать 'listMap' вместо' map'. –

+2

Я просто хотел указать на него новичка, поскольку вы не упомянули об этом конкретно. Проблема с вашими предложениями в том, что они делают экспертов демографическими, которые, вероятно, будут знать о дружелюбной с новичком стороне Haskell, и новички будут пытаться понять экспертную сторону по умолчанию Haskell - совершенно противоположное тому, что нужно в простой в освоении язык!Обратное к тому, что вы предлагаете, уже существует в форме [basic-prelude] (http://hackage.haskell.org/packages/archive/basic-prelude/0.3.6.0/doc/html/BasicPrelude.html). – kqr

ответ

24

Почему эти вещи были изменены для Haskell 98 и почему так?

Haskell 98 включает в себя много упрощения для языка (большая часть которого с тех пор была отменена). Цель состояла в том, чтобы улучшить Haskell в качестве учебного языка и сделать относительно консервативный выбор.

См., Например,

Мы рассматривали Haskell 98 как достаточно консервативный дизайн. Например, для классы многопараметрического типа были широко распространены в , но Haskell 98 имеет только классы с одним параметром (Peyton Jones et al., 1997).

В: History of Haskell

И:

Haskell 98 будет далеко не последним пересмотр Haskell. На мы разрабатываем его, зная, что новые языковые расширения (классы многопараметрического типа, универсальные и экзистенциальные количественные показатели, защитные маски и т. Д.) Находятся на пути. Однако Haskell 98 будет иметь особый статус: намерение состоит в том, что Компиляторы Haskell будут продолжать поддерживать Haskell 98 (учитывая соответствующий флаг ) даже после того, как более поздние версии этого языка были определены , и поэтому имя `Haskell 98 'будет ссылаться на фиксированный, стабильный язык .

В: Haskell98 report

Таким образом, вещи были упрощены с целью получения более простой стандарт.

+2

Отличный ответ! Во втором источнике есть хороший список изменений. Я думаю, что я должен посмотреть архивы списков рассылки в период с 1997 по 1998 год. Я уже нашел несколько забавных электронных писем, например, что SPJ (сначала нравится «NPlusKPatterns») (http://code.haskell.org/~dons/haskell -1990-2000/msg00582.html), и [ненавидит его шесть лет спустя] (http://code.haskell.org/~dons/haskell-1990-2000/msg03476.html). –