Haskell

Поделись знанием:
Перейти к: навигация, поиск
Haskell
Класс языка:

функциональный, ленивый, модульный

Тип исполнения:

компилируемый, интерпретируемый

Появился в:

1990

Система типов:

полная сильная статическая с выводом типов

Основные реализации:

GHC, HUGS, NHC, YHC

Диалекты:

Helium, Gofer, O'Haskell, Haskell++, Mondrian,
Disciple

Испытал влияние:

ML и Standard ML, Lazy ML[en], Miranda, Lisp и Scheme, ISWIM, FP[en],
АПЛ, Hope и Hope+, SISAL[en], Orwell[en], Id[en]

Повлиял на:

Agda, Bluespec[en], Clojure, C#, Cat, Cayenne[en], Clean, Curry, Epigram[en], Escher[en], F#, Factor, Isabelle[en], Java Generics, LINQ, Mercury, Ωmega[en], Perl 6, Python, Qi[en], Scala, Timber[en], Visual Basic 9.0

Сайт:

[haskell.org .org]

Haskell (hæskəl) — стандартизированный чистый функциональный язык программирования общего назначения. Является одним из самых распространённых языков программирования с поддержкой отложенных вычислений. Система типов — полная, сильная, статическая, с автоматическим выводом типов, основанная на системе типов Хиндли — Милнера. Поскольку язык функциональный, то основная управляющая структура — это функция.

Отличительная черта языка — серьёзное отношение к типизации; во многом в этой связи язык назван в честь исследователя теории типов и изобретателя комбинаторной логики Хаскелла Карри.

Имеются средства взаимодействия с кодом на других языках программирования. Есть встроенная поддержка многозадачного и параллельного программирования, развитый инструментарий (средства автоматического тестирования, отладки и профилирования, в том числе для параллельных программ), существует несколько тысяч библиотек с открытым исходным кодом.





История

Haskell принадлежит к семейству языков ML. Непосредственно на него оказал большое влияние язык Миранда, разработанный в 1985 году Дэвидом Тёрнером. Миранда была первым чистым функциональным языком, имевшим коммерческую поддержку, и была относительно популярна в 1980-х годах, но оставалась собственническим программным обеспечением. Это затрудняло развитие и исследования возможностей ленивого функционального программирования, поэтому буквально за пару лет появилось более десятка схожих языков. Чтобы объединить усилия разных разработчиков в 1987 году на конференции по функциональным языкам программирования и компьютерной архитектуре в Орегоне (FPCA’87) было решено создать комитет для разработки открытого стандарта.

В 1990 году была предложена первая версия языка, Haskell 1.0. В дальнейшем работа комитета продолжилась, и в 1999 году был опубликован «The Haskell 98 Report»[1], который стал стабильным стандартом языка на много лет. Язык, однако, продолжал бурно развиваться, компилятор GHC был фактическим стандартом в отношении новых возможностей.

Разработка новых версий языка идёт открыто, этот процесс получил название Haskell’[2] (Haskell Prime [ˈhæskəl praɪm], «Хаскелл-штрих»). Все желающие могут выдвигать свои предложения к обсуждению, предложения обсуждаются в течение года, комитет отбирает и объявляет предложения, которые готов принять, формируется новый комитет и к концу года готовится новая версия языка. Таким образом, новые версии языка теперь могут появляться каждый год. Планируется объявлять некоторые ревизии «значительными» и поддерживать такие ревизии на протяжении длительного времени.

Версия языка Haskell 2010 — была объявлена в конце 2009 г[3], но последней «значительной» версией (стандартом) остаётся Haskell 98.

Характеристики языка

В качестве основных характеристик языка Haskell можно выделить следующие:

С момента принятия последнего стандарта языка (Haskell98) прошло много времени, и с тех пор ведущие реализации языка (ghc и hugs) были расширены множеством дополнительных возможностей:

Реализации языка

Есть несколько реализаций языка Haskell[5]. Некоторые реализации ориентированы на практическое применение, в то время как другие — представляют прежде всего академический интерес.

Компиляторы и интерпретаторы

Наиболее популяренК:Википедия:Статьи без источников (тип: не указан)[источник не указан 4007 дней] на практике оптимизирующий компилятор GHC, который создаёт быстрый код и позволяет использовать многие расширения языка. GHC может оптимизировать как скорость, так и компактность программ, способен создавать многозадачный и параллелизованный код. В комплекте с компилятором GHC поставляется также интерактивная среда программирования GHCi со встроенным отладчиком. GHC работает в Windows, MacOS X и на нескольких юникс-подобных платформах (Linux, *BSD, Solaris). Именно GHC является стандартным компилятором в Haskell Platform, и именно на нём в первую очередь тестируются все новые библиотеки.

Другая популярная реализация языка — интерпретатор HUGS. Он написан на Си, имеет малый размер дистрибутива и работает практически на всех платформах. HUGS предоставляет интерактивную среду программирования, но может также запускать программы на Haskell в стиле скриптовых языков. Пользователи Windows могут использовать графическую интерактивную среду WinHugs. Поскольку HUGS — это интерпретатор, то программы, запущенные в нём, выполняются медленнее, чем код, созданный большинством компиляторов языка Haskell. HUGS часто рекомендуют в качестве среды для изучения языка. HUGS полностью поддерживает стандарт языка Haskell 98, а также некоторые наиболее популярные расширения языка.

Другие известные реализации:

  • nhc98 — быстрый компилятор, поддерживающий стандарт Haskell 98, написанный на Haskell 98; доступен для всех юникс-подобных платформ, включая MacOS X и Windows/cygwin
  • YHC (York Haskell Compiler) — форк nhc98, ставящий целью быть более переносимым и эффективным, поддерживает отладчик Hat; генерирует промежуточный байт-код, который можно использовать для генерации кода на других языках программирования
  • UHC (Utrecht Haskell Compiler) — компилятор, поддерживающий Haskell 98 почти полностью, а также некоторые расширения; поддерживает глобальный анализ программ; имеет несколько кодогенераторов, в том числе почти полностью функциональный генератор JVM-кода, кодогенераторы для LLVM и CLR в состоянии разработки; работает на юникс-подобных системах (включая MacOS X и Windows/cygwin)
  • HBI и HBC — интерпретатор и компилятор, поддерживающие стандарт Haskell 98 с некоторыми расширениями; точно работает в Linux, поддерживается слабо
  • LHC (The Luxurious LHC Haskell Optimization System) — альтернативный кодогенератор для GHC, поддерживающий глобальную низкоуровневую оптимизацию программы в целом
  • jhc — экспериментальный компилятор для исследования возможностей глобальной оптимизации программ
  • Yale Haskell — ранняя реализация языка Haskell на Lisp

Haskell Platform

В 2009 году сформировалась концепция Haskell Platform[6] — стандартного дистрибутива языка, включающего кроме компилятора (GHC), также дополнительный инструментарий (систему сборки и развёртывания пакетов Cabal) и набор популярных библиотек.

Сейчас Haskell Platform — это рекомендованный базовый дистрибутив для разработчиков. Готовые сборки Haskell Platform доступны для Windows, MacOS X и ряда дистрибутивов Linux.

Альтернативные целевые платформы

Большинство компиляторов языка Haskell создают непосредственно машинный код для используемой платформы, но есть несколько проектов, позволяющих производить код для виртуальных машин или генерировать код на других языках программирования. Степень зрелости и уровень поддержки подобных проектов сильно разнится.

  • LLVM:
    • патч для GHC[7], добавляющий генератор кода для LLVM, в настоящее время включен в компилятор GHC[8]; использование LLVM позволяет достичь большей производительности на ряде задач[9].
    • альтернативный кодогенератор в UHT (работоспособен частично)
  • виртуальная машина Java (JVM):
    • LambdaVM[10] — патч для GHC, добавляющий генератор байткода JVM
    • jvm-bridge[11] — мост между Haskell и JVM (для GHC)
    • jaskell[12] — генератор байт-кода JVM (вероятно заброшен)
    • альтернативный кодогенератор в UHC (работоспособен почти полностью)
  • Common Language Runtime (.Net):
    • прототип генератора MSIL-кода[13] для компилятора EHT/UHT
    • некоторые проекты по поддержке CLR упоминаются в GHC FAQ[14], на начало 2010 года их состояние не ясно
  • JavaScript:
    • кодогенератор JavaScript для GHC[15] — патч для GHC позволяющий компилировать программы в JavaScript-код
    • Ycr2Js[16] — конвертер байт-кода компилятора YHC в JavaScript
    • Fay — компилятор подмножества Haskell в JavaScript[17]

Несколько интересных целевых платформ доступны при использовании компилятора YHC, в частности существуют интерпретатор байт-кода YHC на Python и конвертер байт-кода YHC в Erlang Core, но эти разработки пока ещё экспериментальны. Также существуют реализации подмножеств языка на разных целевых платформах.

Расширения языка

Расширения реализаций языка (относится к GHC):

Примеры

Вычисление факториала

Следующий пример показывает синтаксис языка Haskell при реализации функции для вычисления факториала:

 fac :: Integer -> Integer
 fac 0 = 1
 fac n | n > 0 = n * fac (n - 1)

Это определение описывает процесс вычисления факториала в виде рекурсивной функции. Это определение похоже на то, которое можно найти в учебниках по информатике. Большая часть исходного кода на языке Haskell походит на математическую нотацию в аспектах синтаксиса и использования, например, вышеприведённый пример можно переписать в виде

fac n = product [1..n]

что соответствует математическому определению факториала.

Первая строка в приведённом выше коде необязательна и является объявлением функционального типа, то есть задаёт типы аргументов (указаны до последней «->») и тип возвращаемого значения (указан после последней «->»). Эта строка может быть прочитана как: функция fac имеет тип (::) из целого в целое (Integer -> Integer). Это значит, что она получает на вход один целочисленный аргумент (записан слева от «->») и возвращает результат также целого типа (записан справа от «->»). Если программист не указал типы явно, компилятор или интерпретатор может определить их автоматически.

Вторая и третья строки формируют определение тела функции. Определение состоит из предложений, или «клауз» (англ. clause). Каждое предложение представляет собой пару «образец — выражение». Компилятор или интерпретатор использует механизм сопоставления с образцом для выбора одного из выражений. В данном случае вторая строка определения будет выбрана тогда, когда фактический параметр при вызове функции fac будет равен нулю.

В третьей строке помимо механизма сопоставления с образцами использовано охраняющее выражение — n > 0. Оно гарантирует, что функция не будет работать для отрицательных чисел, для которых факториал неопределён. Если отрицательное число будет передано в качестве фактического параметра в функцию fac, то программа остановится с сообщением об ошибке.

Калькулятор

Простейший калькулятор для вычисления выражений в обратной польской записи может быть определён на языке Haskell при помощи одной функции:

 calc :: String -> Float
 calc = head . foldl f [] . words
   where 
     f :: [Float] -> String -> [Float]
     f (x:y:zs) "+"    = (y + x):zs
     f (x:y:zs) "-"    = (y - x):zs
     f (x:y:zs) "*"    = (y * x):zs
     f (x:y:zs) "/"    = (y / x):zs
     f (x:y:zs) "FLIP" = y:x:zs
     f (x:zs)   "ABS"  = (abs x):zs
     f xs       y      = read y : xs

Исходная строка со входным выражением тут разбивается стандартной функцией words на список слов — строк между пробельными символами — который обрабатывается функцией левосторонней свёртки (foldl) слева направо по одному слову с помощью функции f, которая поддерживает рабочий список прочитываемых чисел и промежуточных значений (поначалу [] — пустой список) и интерпретирует каждое входное слово как обозначение арифметической функции или как число, в ходе вычисления ею окончательного значения выражения (которое будет первым оставшимся значением в рабочем списке по окончании обработки списка слов входного выражения, так что его можно достать оттуда с помощью стандартной функции head).

Здесь (.) есть оператор композиции функций, (f . g) x = f (g x). Например,

*Main> calc "1 2 3 + 4 * - ABS"
19.0

Числа Фибоначчи

Другой пример показывает способ вычисления бесконечного списка чисел Фибоначчи за линейное время:

fibs = 0 : 1 : zipWith (+) fibs (tail fibs)

Бесконечный список здесь определен при помощи механизма корекурсии — последующие значения списка здесь задаются на основе предыдущих, с начальными 0 и 1 в качестве первых двух элементов списка, и выражением-генератором zipWith (+) fibs (tail fibs), вычисляющим все элементы начиная с третьего на основании предшествующих двух, через стандартную функцию zipWith (+) которая суммирует попарно элементы двух своих входных списков.

Это определение является примером применения механизма ленивых вычислений, который является важнейшей частью языка Haskell. Для понимания того, как это определение работает, можно рассмотреть вычисление первых семи чисел Фибоначчи с его помощью:

fibs         = 0 : 1 : 1 : 2 : 3 : 5 : 8 : ...
               +   +   +   +   +   +
tail fibs    = 1 : 1 : 2 : 3 : 5 : 8 : ...
               =   =   =   =   =   =
zipWith (+)  = 1 : 2 : 3 : 5 : 8 : ...
fibs = 0 : 1 : 1 : 2 : 3 : 5 : 8 : ...

То же самое может быть записано также при использовании определителей списков,

 fibs = 0 : 1 : [a + b | (a,b) <- zip fibs (tail fibs)]

или расширения языка Haskell, реализованного в компиляторе GHC (параллельных определителей списков, англ. parallel list comprehensions):

 fibs = 0 : 1 : [a + b | a <- fibs       
                       | b <- tail fibs]

или с помощью напрямую самореферентной генерирующей функции:

 fibs = 0 : 1 : next fibs
   where
     next (a: t@(b:_)) = (a+b) : next t

Простые числа

В этих примерах показано, как можно использовать списочные выражения (генераторы списков). Реализация нахождения всех простых чисел обычным путём (проверка каждого числа на простоту):

 -- общее определение (все натуральные числа > 1, которые являются простыми)
 primeNums = 2 : [n | n <- [3..], isPrime n]
 
 -- Число простое, если у него нет (простых) делителей
 isPrime n = foldr (\p r-> p*p>n || (rem n p /= 0 && r)) True primeNums

или по-сегментным перебором делителей,

primesST = 2 : 3 : sieve 0 5 9 (drop 2 primesST)
  where
    sieve k x q ps = let fs = take k (tail primesST) in
      [n | n <- [x,x+2..q-2], all ((/=0).rem n) fs]
      ++ sieve (k+1) (q+2) (head ps^2) (tail ps)

а также с помощью решета Эратосфена, в варианте ограниченного списка,

 primesTo m = 2 : eratos [3,5..m] where
   eratos (x : xs) | x*x>m = x : xs
                   | True  = x : eratos (xs `minus` [x*x, x*x+2*x..m])

или, вообще говоря, бесконечного списка простых чисел:

 primes = 2 : ([3,5..] `minus` unionAll [[p*p, p*p+2*p..] | p <- primes'])
   where 
     primes' =  3 : ([5,7..] `minus` unionAll [[p*p, p*p+2*p..] | p <- primes']) 
     unionAll ((x:xs):t) = x : union xs (unionAll (pairs t))
     pairs ((x:xs):ys:t) = (x : union xs ys) : pairs t

с использованием канонических функций minus, union (в том числе из пакета [hackage.haskell.org/packages/archive/data-ordlist/0.4.4/doc/html/Data-List-Ordered.html Data.List.Ordered]):

union (x:xs) (y:ys) = case compare x y of
         LT -> x : union  xs (y:ys)
         EQ -> x : union  xs    ys
         GT -> y : union (x:xs) ys
union a b = a ++ b
minus (x:xs) (y:ys) = case compare x y of
         LT -> x : minus  xs (y:ys)
         EQ ->     minus  xs    ys
         GT ->     minus (x:xs) ys
minus a b = a

Описание игральных карт

Простой пример использования алгебраических типов данных для описания игральных карт. Идентификаторы типов начинаются с заглавных букв. Идентификаторы переменных и функций — со строчных. Новые алгебраические типы определяются ключевым словом data. Синонимы типов определяются ключевым словом type.

-- Алгебраический тип-сумма Масть («перечисление»).
-- Значением типа Масть может быть одно из указанных справа
-- (или Пики, или Трефы, или Бубны, или Червы).
-- «Масть» здесь выступает конструктором _типа_,
-- а «Пики», «Трефы» и т.д. — конструкторами _данных_.
data Масть = Пики | Трефы | Бубны | Червы
  -- необязательное автоматическое выведение экземпляров классов,
  -- позволяющее преобразовывать значения в строки (функцией show из Show)
  -- и обратно (функцией read из Read), а также сравнивать их между собой
  -- (функциями классов Eq и Ord).
  deriving (Show, Read, Eq, Ord)

-- Алгебраический тип-сумма Достоинство
data Достоинство = Семёрка | Восьмёрка | Девятка | Десятка
                 | Валет | Дама | Король | Туз
  deriving (Show, Read, Eq, Ord)

-- Алгебраический тип-произведение Карта («тип-кортеж»).
-- Значения типа Карта — комбинации значений типов Достоинство и Масть,
-- объединённые конструктором данных К.
-- Часто имена конструктора данных и конструктора типа совпадают.
data Карта = К Достоинство Масть
  deriving (Show, Read, Eq, Ord)

-- Синоним списка значений типа Карта.
type Рука = [Карта]

-- Функция, определяющая, есть ли в руке марьяж (король и дама одной масти).
естьМарьяж :: Рука -> Bool
естьМарьяж карты =
   -- достаточно найти марьяж хотя бы одной масти
   any (естьМарьяжМасти) [Пики, Трефы, Бубны, Червы]
   where
     -- проверить, есть ли и дама, и король заданной масти м в руке
     естьМарьяжМасти м = (К Дама м) `elem` карты && (К Король м) `elem` карты

-- примеры раздач
рука = [ К Дама Трефы, К Семёрка Червы, К Король Трефы, К Туз Бубны ]
рука_без_марьяжа = [ К Десятка Пики, К Король Пики, К Дама Червы ]

main = do
  проверить рука
  проверить рука_без_марьяжа
  проверить [] -- пустая раздача
  where
    проверить кк = putStrLn ( (show кк) ++ " -> " ++ (show (естьМарьяж кк)) )

-- Вывод:
-- [К Дама Трефы,К Семёрка Червы,К Король Трефы,К Туз Бубны] -> True
-- [К Десятка Пики,К Король Пики,К Дама Червы] -> False
-- [] -> False

Численное интегрирование

Численное интегрирование <math>\int\limits_0^{2\pi}x\sin x\,{\rm d}x = -2\pi</math> методом трапеций:
trapezeIntegrate f a b n =
    ((sum $ map f [a + h, a + 2*h .. b - h]) + t) * h
    where
        t = (f a + f b)/2
        h = (b - a) / n

main = do
    print $ trapezeIntegrate (\x -> x*sin x) 0 (2*pi) 100

-- Вывод: -6.281118086046067

Проверка палиндромов

В примере ниже демонстрируется работа со строками в Юникоде.

import Data.Char (toLower, isAlpha)

palindrom :: [Char] -> Bool
palindrom s =
    norm == reverse norm
    where norm = map toLower $ filter isAlpha $ s

test :: [Char] -> IO ()
test s =
    putStrLn $ s ++ ": " ++ show (palindrom s)

main = do
    test "А в Енисее — синева"
    test "А роза упала на лапу Азора"
    test "Не роза упала на лапу Азора"
    test "Мир как Рим"
    test "Мир не Рим"
    test "Dogma: I am God"
    test "I prefer Pi"
    test "حوت فمه مفتوح"
    test "Ne mateno, bone tamen"

-- Вывод:
-- А в Енисее — синева: True
-- А роза упала на лапу Азора: True
-- Не роза упала на лапу Азора: False
-- Мир как Рим: True
-- Мир не Рим: False
-- Dogma: I am God: True
-- I prefer Pi: True
-- حوت فمه مفتوح: True
-- Ne mateno, bone tamen: True

Приложения, написанные на языке Haskell

Мозаичный оконный менеджер Xmonad для X Window System целиком написан на языке Haskell. Darcs — распределённая система управления версиями с рядом уникальных возможностей — написана на Haskell. Первая реализация компилятора и интерпретатора языка Perl 6, Pugs, была написана на Haskell за несколько месяцев. Компилятор GHC часто выступает экспериментальной площадкой для проверки новых возможностей функционального программирования и оптимизации.

Коммерческие приложения

Haskell всё чаще используется в коммерческой среде[18]. Этому способствует и принятая в сообществе традиция выпускать библиотеки под либеральными лицензиями (более 70 % свободно доступных библиотек распространяются на условиях лицензий BSD, MIT или являются общественным достоянием).

Вот примеры некоторых коммерческих приложений, написанных на Haskell: Bluespec SystemVerilog, встраиваемый язык проектирования и верификации полупроводниковых схем, является расширением языка Haskell[19]. Cryptol, коммерческий язык для разработки и проверки криптографических алгоритмов, реализован на Haskell. Примечательно, что первое формально верифицированное микроядро seL4 было тоже написано на Haskell.

Haskell активно применяется в области финансового программирования, анализа рисков, в системах поддержки решений. Haskell применяют разработчики генератора городских ландшафтов для игр и моделирования Gamr7[20]. Есть примеры успешного применения языка для разработки частных информационных систем в коммерческих организациях (в том числе, в странах СНГ)[21].

Приложения с открытым исходным кодом

Также на Haskell написано много приложений c открытым исходным кодом. Большинство из них доступны в архиве Hackage, ниже приведены некоторые из них.

Базы данных
  • haskelldb — строго типизированный интерфейс доступа к SQL-базам данных;
  • HDBC — универсальный интерфейс доступа к реляционным базам данных (поддерживаются SQLite, MySQL, PostgreSQL, ODBC);
  • Takusen — библиотека доступа к базам данных, использующая интерфейс левой свёртки;
  • есть библиотеки для работы с BerkeleyDB, CouchDB, MongoDB, Redis, TokyoCabinet и TokyoTyrant, SimpleDB, SQLite;
Графика
  • Blobs — редактор диаграмм;
  • Diagrams — библиотека для программирования схем и диаграмм;
  • FieldTrip — библиотека для функционального описания 3D-объектов;
  • Glome — один из множества трассировщиков лучей;
  • GLUT и OpenGL — интерфейсы для использования GLUT и OpenGL;
  • GPipe — функциональный интерфейс для программирования GPU;
  • Grapefruit — библиотека для функционального реактивного программирования графики и интерфейсов;
  • Haven — библиотека отрисовки масштабируемой векторной графики;
  • HaskellCharts — библиотека для отрисовки двумерных графиков;
  • SDL — интерфейс для использования libSDL из Haskell;
  • Yampa — встраиваемый язык для функционального реактивного программирования с помощью стрелок;
Графические интерфейсы
  • Gtk2Hs — библиотека для создания графических интерфейсов на основе GTK+;
  • Grapefruit и wxFruit — библиотеки декларативного программирования интерфейсов (на основе реактивного программирования);
  • qtHaskell — библиотека для создания графических интерфейсов на основе Qt;
  • wxHaskell — библиотека для создания графических интерфейсов на основе wxWidgets;
  • HTk — библиотека для создания графических интерфейсов на основе Tk;
Игры
  • bloxorz — трёхмерная логическая игра;
  • Frag — трёхмерный шутер от первого лица;
  • monadius — двумерный скроллер;
  • Raincat — рисованная игра-головоломка;
Интернет
  • gitit — вики-платформа, основанная на системах контроля версиями (darcs, git или mercurial);
  • happstack — фреймворк для веб-программирования (аналог Django или Ruby on Rails);
  • Twidge — терминальный клиент для микроблоггинга;
Обработка текста
  • HaXml — многофункциональная библиотека для работы с XML;
  • HXT — комбинаторная библиотека для работы с XML, использующая выразительный предметно-ориентированный язык, основанный на стрелках (англ. arrows);
  • Leksah — интегрированная среда разработки, написанная на Haskell и, в основном, для разработки на Haskell; поддерживает навигацию по исходным текстом, автодополнение, отладку и сборку пакетов;
  • Pandoc — универсальный конвертер текста между различными языками разметки;
  • Parsec — комбинаторная библиотека для синтаксического анализа
  • The Grammatical Framework — библиотека для работы с текстом на естественных языках;
  • Шаблон:Iw:Yi — текстовый редактор подобный Emacs, написанный на Haskell и использующий его в качестве скриптового языка;
Параллельное, многозадачное и многопоточное программирование
  • CHP — Communicating Haskell Processes, библиотека, реализующая модель параллельных процессов без общей памяти;
  • Data Parallel Haskell — расширение языка, обеспечивающие параллелизм данных на многоядерных процессорах;
  • parallel — стандартная библиотека для параллельного программирования;
  • STM — реализация программной транзакционной памяти.
Разработка
Системные программы
  • Darcs — продвинутая распределённая система контроля версий;
  • House — операционная система, написанная на Haskell;
  • Xmonad — мозаичный менеджер окон;
  • Himerge — графическая оболочка для Emerge — пакетного менеджера Gentoo;
  • FreeArc — архиватор;
Языки и компиляторы
  • Agda — язык программирования с зависимыми типами и доказатель теорем;
  • Curry — функционально-логический язык, реализованный поверх Хаскела;
  • cpphs — реализация препроцессора языка Си;
  • Epigram (англ.) — язык программирования с зависимыми типами;
  • Flapjax — язык для реактивного программирования веб-приложений;
  • Language.Python — библиотека лексического и синтаксического анализа кода на языке Python;
  • Language.C — библиотека анализа и генерации кода на языке Си;
  • Lava — язык аппаратных схем;
  • llvm — интерфейс для работы с LLVM из Haskell;
  • Pugs — компилятор и интерпретатор языка Perl 6;
  • WebBits — библиотека для работы с кодом на языке Javascript.

См. также

Напишите отзыв о статье "Haskell"

Примечания

  1. [www.haskell.org/onlinereport/ The Haskell 98 Language Report] — получено 05.02.2010
  2. [hackage.haskell.org/trac/haskell-prime/ Haskell Prime]
  3. [www.haskell.org/pipermail/haskell/2009-November/021750.html Simon Marlow, Announcing Haskell 2010]
  4. [www.cse.unsw.edu.au/~chak/haskell/ffi/ The Haskell 98 Foreign Function Interface 1.0: An Addendum to the Haskell 98 Report ]
  5. [www.haskell.org/haskellwiki/Implementations Реализации языка Haskell (англ.)]
  6. [hackage.haskell.org/platform/ The Haskell Platform]
  7. [www.haskell.org/pipermail/cvs-ghc/2010-February/052606.html Merge Request: LLVM Code Generator for GHC]
  8. [blog.llvm.org/2010/05/glasgow-haskell-compiler-and-llvm.html The Glasgow Haskell Compiler and LLVM]
  9. [donsbot.wordpress.com/2010/02/21/smoking-fast-haskell-code-using-ghcs-new-llvm-codegen/ Smoking fast Haskell code using GHC’s new LLVM codegen]
  10. [wiki.brianweb.net/LambdaVM/LambdaVM LambdaVM]
  11. [semantic.org/jvm-bridge/ JVM-Bridge]
  12. [www.scdi.org/~avernet/projects/jaskell/ The Jaskell Project Home Page]
  13. [tom.lokhorst.eu/ehc/clr/ Running Haskell on the CLR (using UHC)]
  14. [www.haskell.org/haskellwiki/GHC:FAQ#Why_isn.27t_GHC_available_for_.NET_or_on_the_JVM.3F 1.5.1 Why isn’t GHC available for .NET or on the JVM?]
  15. [vir.mskhug.ru/ кодогенератор JavaScript для GHC](недоступная ссылка — историякопия)
  16. [haskell.org/haskellwiki/Yhc/Javascript Yhc/Javascript, YCR2JS, a Converter of Yhc Core to Javascript]
  17. [github.com/faylang/fay/wiki Home · faylang/fay Wiki · GitHub]
  18.  (англ.)[www.haskell.org/haskellwiki/Haskell_in_industry Коммерческие применения языка Haskell]
  19. [homepages.inf.ed.ac.uk/wadler/realworld/bluespec.html Bluespec]
  20. [gamr7.com/ Gamr7: UrbanPAD. The Software for 3D city & buildings creation.]
  21. Астапов Дмитрий [fprog.ru/2009/issue2/ Использование Haskell при поддержке критически важной для бизнеса информационной системы] // Практика функционального программирования : Журнал. — 2009. — № 2. — С. 53—69.

Литература

  • Bryan O’Sullivan, John Goerzen, Don Stewart. Real World Haskell — O’Reilly, 2008—710 °C. ISBN 0-596-51498-0. ISBN 978-0-596-51498-3
  • Душкин Роман Викторович. Функциональное программирование на языке Haskell / Гл. ред. Д. А. Мовчан;. — М.: ДМК Пресс,, 2008. — 544 с., ил. с. — 1500 экз. — ISBN 5-94074-335-8.

Ссылки

  • [haskell.org .org] — основной сайт, посвящённый языку Haskell; содержит различные справочные материалы, список интерпретаторов и компиляторов Haskell (в настоящий момент, все интерпретаторы и компиляторы бесплатны). Кроме того, имеется обширный список ссылок на ресурсы по теории функционального программирования и другим языкам (Standard ML, Clean).
Учебный и справочный материал
  • [www.haskell.ru/ Полный перевод описания языка Haskell на русский язык].
  • Сайт-книга [learnyouahaskell.com/ «Learn You a Haskell for Great Good!»].
  • Роман Душкин. [www.roman-dushkin.narod.ru/fp.html Курс лекций по функциональному программированию] (читается в МИФИ с 2001 года).
  • Артём Гавриченков, Фёдор Сахаров. [haskell.secsem.ru/2010/Lectures Спецкурс «Теория функционального программирования. Язык Haskell»] (лецкии и презентации, прочитан на ВМиК МГУ в 2010 году)
  • Пол Хьюдак, Джон Петерсон, Джозеф Фасел. [www.rsdn.ru/article/haskell/haskell_part1.xml Мягкое введение в Haskell, часть 1] (рус.). RSDN (3 марта 2007). Проверено 13 апреля 2014.; [rsdn.ru/article/haskell/haskell_part2.xml часть 2].
  • Денис Шевченко. [github.com/denisshevchenko/ohaskell.guide О Haskell по-человечески]. github.

Отрывок, характеризующий Haskell

Больше Яков Алпатыч не настаивал. Он долго управлял народом и знал, что главное средство для того, чтобы люди повиновались, состоит в том, чтобы не показывать им сомнения в том, что они могут не повиноваться. Добившись от Дрона покорного «слушаю с», Яков Алпатыч удовлетворился этим, хотя он не только сомневался, но почти был уверен в том, что подводы без помощи воинской команды не будут доставлены.
И действительно, к вечеру подводы не были собраны. На деревне у кабака была опять сходка, и на сходке положено было угнать лошадей в лес и не выдавать подвод. Ничего не говоря об этом княжне, Алпатыч велел сложить с пришедших из Лысых Гор свою собственную кладь и приготовить этих лошадей под кареты княжны, а сам поехал к начальству.

Х
После похорон отца княжна Марья заперлась в своей комнате и никого не впускала к себе. К двери подошла девушка сказать, что Алпатыч пришел спросить приказания об отъезде. (Это было еще до разговора Алпатыча с Дроном.) Княжна Марья приподнялась с дивана, на котором она лежала, и сквозь затворенную дверь проговорила, что она никуда и никогда не поедет и просит, чтобы ее оставили в покое.
Окна комнаты, в которой лежала княжна Марья, были на запад. Она лежала на диване лицом к стене и, перебирая пальцами пуговицы на кожаной подушке, видела только эту подушку, и неясные мысли ее были сосредоточены на одном: она думала о невозвратимости смерти и о той своей душевной мерзости, которой она не знала до сих пор и которая выказалась во время болезни ее отца. Она хотела, но не смела молиться, не смела в том душевном состоянии, в котором она находилась, обращаться к богу. Она долго лежала в этом положении.
Солнце зашло на другую сторону дома и косыми вечерними лучами в открытые окна осветило комнату и часть сафьянной подушки, на которую смотрела княжна Марья. Ход мыслей ее вдруг приостановился. Она бессознательно приподнялась, оправила волоса, встала и подошла к окну, невольно вдыхая в себя прохладу ясного, но ветреного вечера.
«Да, теперь тебе удобно любоваться вечером! Его уж нет, и никто тебе не помешает», – сказала она себе, и, опустившись на стул, она упала головой на подоконник.
Кто то нежным и тихим голосом назвал ее со стороны сада и поцеловал в голову. Она оглянулась. Это была m lle Bourienne, в черном платье и плерезах. Она тихо подошла к княжне Марье, со вздохом поцеловала ее и тотчас же заплакала. Княжна Марья оглянулась на нее. Все прежние столкновения с нею, ревность к ней, вспомнились княжне Марье; вспомнилось и то, как он последнее время изменился к m lle Bourienne, не мог ее видеть, и, стало быть, как несправедливы были те упреки, которые княжна Марья в душе своей делала ей. «Да и мне ли, мне ли, желавшей его смерти, осуждать кого нибудь! – подумала она.
Княжне Марье живо представилось положение m lle Bourienne, в последнее время отдаленной от ее общества, но вместе с тем зависящей от нее и живущей в чужом доме. И ей стало жалко ее. Она кротко вопросительно посмотрела на нее и протянула ей руку. M lle Bourienne тотчас заплакала, стала целовать ее руку и говорить о горе, постигшем княжну, делая себя участницей этого горя. Она говорила о том, что единственное утешение в ее горе есть то, что княжна позволила ей разделить его с нею. Она говорила, что все бывшие недоразумения должны уничтожиться перед великим горем, что она чувствует себя чистой перед всеми и что он оттуда видит ее любовь и благодарность. Княжна слушала ее, не понимая ее слов, но изредка взглядывая на нее и вслушиваясь в звуки ее голоса.
– Ваше положение вдвойне ужасно, милая княжна, – помолчав немного, сказала m lle Bourienne. – Я понимаю, что вы не могли и не можете думать о себе; но я моей любовью к вам обязана это сделать… Алпатыч был у вас? Говорил он с вами об отъезде? – спросила она.
Княжна Марья не отвечала. Она не понимала, куда и кто должен был ехать. «Разве можно было что нибудь предпринимать теперь, думать о чем нибудь? Разве не все равно? Она не отвечала.
– Вы знаете ли, chere Marie, – сказала m lle Bourienne, – знаете ли, что мы в опасности, что мы окружены французами; ехать теперь опасно. Ежели мы поедем, мы почти наверное попадем в плен, и бог знает…
Княжна Марья смотрела на свою подругу, не понимая того, что она говорила.
– Ах, ежели бы кто нибудь знал, как мне все все равно теперь, – сказала она. – Разумеется, я ни за что не желала бы уехать от него… Алпатыч мне говорил что то об отъезде… Поговорите с ним, я ничего, ничего не могу и не хочу…
– Я говорила с ним. Он надеется, что мы успеем уехать завтра; но я думаю, что теперь лучше бы было остаться здесь, – сказала m lle Bourienne. – Потому что, согласитесь, chere Marie, попасть в руки солдат или бунтующих мужиков на дороге – было бы ужасно. – M lle Bourienne достала из ридикюля объявление на нерусской необыкновенной бумаге французского генерала Рамо о том, чтобы жители не покидали своих домов, что им оказано будет должное покровительство французскими властями, и подала ее княжне.
– Я думаю, что лучше обратиться к этому генералу, – сказала m lle Bourienne, – и я уверена, что вам будет оказано должное уважение.
Княжна Марья читала бумагу, и сухие рыдания задергали ее лицо.
– Через кого вы получили это? – сказала она.
– Вероятно, узнали, что я француженка по имени, – краснея, сказала m lle Bourienne.
Княжна Марья с бумагой в руке встала от окна и с бледным лицом вышла из комнаты и пошла в бывший кабинет князя Андрея.
– Дуняша, позовите ко мне Алпатыча, Дронушку, кого нибудь, – сказала княжна Марья, – и скажите Амалье Карловне, чтобы она не входила ко мне, – прибавила она, услыхав голос m lle Bourienne. – Поскорее ехать! Ехать скорее! – говорила княжна Марья, ужасаясь мысли о том, что она могла остаться во власти французов.
«Чтобы князь Андрей знал, что она во власти французов! Чтоб она, дочь князя Николая Андреича Болконского, просила господина генерала Рамо оказать ей покровительство и пользовалась его благодеяниями! – Эта мысль приводила ее в ужас, заставляла ее содрогаться, краснеть и чувствовать еще не испытанные ею припадки злобы и гордости. Все, что только было тяжелого и, главное, оскорбительного в ее положении, живо представлялось ей. «Они, французы, поселятся в этом доме; господин генерал Рамо займет кабинет князя Андрея; будет для забавы перебирать и читать его письма и бумаги. M lle Bourienne lui fera les honneurs de Богучарово. [Мадемуазель Бурьен будет принимать его с почестями в Богучарове.] Мне дадут комнатку из милости; солдаты разорят свежую могилу отца, чтобы снять с него кресты и звезды; они мне будут рассказывать о победах над русскими, будут притворно выражать сочувствие моему горю… – думала княжна Марья не своими мыслями, но чувствуя себя обязанной думать за себя мыслями своего отца и брата. Для нее лично было все равно, где бы ни оставаться и что бы с ней ни было; но она чувствовала себя вместе с тем представительницей своего покойного отца и князя Андрея. Она невольно думала их мыслями и чувствовала их чувствами. Что бы они сказали, что бы они сделали теперь, то самое она чувствовала необходимым сделать. Она пошла в кабинет князя Андрея и, стараясь проникнуться его мыслями, обдумывала свое положение.
Требования жизни, которые она считала уничтоженными со смертью отца, вдруг с новой, еще неизвестной силой возникли перед княжной Марьей и охватили ее. Взволнованная, красная, она ходила по комнате, требуя к себе то Алпатыча, то Михаила Ивановича, то Тихона, то Дрона. Дуняша, няня и все девушки ничего не могли сказать о том, в какой мере справедливо было то, что объявила m lle Bourienne. Алпатыча не было дома: он уехал к начальству. Призванный Михаил Иваныч, архитектор, явившийся к княжне Марье с заспанными глазами, ничего не мог сказать ей. Он точно с той же улыбкой согласия, с которой он привык в продолжение пятнадцати лет отвечать, не выражая своего мнения, на обращения старого князя, отвечал на вопросы княжны Марьи, так что ничего определенного нельзя было вывести из его ответов. Призванный старый камердинер Тихон, с опавшим и осунувшимся лицом, носившим на себе отпечаток неизлечимого горя, отвечал «слушаю с» на все вопросы княжны Марьи и едва удерживался от рыданий, глядя на нее.
Наконец вошел в комнату староста Дрон и, низко поклонившись княжне, остановился у притолоки.
Княжна Марья прошлась по комнате и остановилась против него.
– Дронушка, – сказала княжна Марья, видевшая в нем несомненного друга, того самого Дронушку, который из своей ежегодной поездки на ярмарку в Вязьму привозил ей всякий раз и с улыбкой подавал свой особенный пряник. – Дронушка, теперь, после нашего несчастия, – начала она и замолчала, не в силах говорить дальше.
– Все под богом ходим, – со вздохом сказал он. Они помолчали.
– Дронушка, Алпатыч куда то уехал, мне не к кому обратиться. Правду ли мне говорят, что мне и уехать нельзя?
– Отчего же тебе не ехать, ваше сиятельство, ехать можно, – сказал Дрон.
– Мне сказали, что опасно от неприятеля. Голубчик, я ничего не могу, ничего не понимаю, со мной никого нет. Я непременно хочу ехать ночью или завтра рано утром. – Дрон молчал. Он исподлобья взглянул на княжну Марью.
– Лошадей нет, – сказал он, – я и Яков Алпатычу говорил.
– Отчего же нет? – сказала княжна.
– Все от божьего наказания, – сказал Дрон. – Какие лошади были, под войска разобрали, а какие подохли, нынче год какой. Не то лошадей кормить, а как бы самим с голоду не помереть! И так по три дня не емши сидят. Нет ничего, разорили вконец.
Княжна Марья внимательно слушала то, что он говорил ей.
– Мужики разорены? У них хлеба нет? – спросила она.
– Голодной смертью помирают, – сказал Дрон, – не то что подводы…
– Да отчего же ты не сказал, Дронушка? Разве нельзя помочь? Я все сделаю, что могу… – Княжне Марье странно было думать, что теперь, в такую минуту, когда такое горе наполняло ее душу, могли быть люди богатые и бедные и что могли богатые не помочь бедным. Она смутно знала и слышала, что бывает господский хлеб и что его дают мужикам. Она знала тоже, что ни брат, ни отец ее не отказали бы в нужде мужикам; она только боялась ошибиться как нибудь в словах насчет этой раздачи мужикам хлеба, которым она хотела распорядиться. Она была рада тому, что ей представился предлог заботы, такой, для которой ей не совестно забыть свое горе. Она стала расспрашивать Дронушку подробности о нуждах мужиков и о том, что есть господского в Богучарове.
– Ведь у нас есть хлеб господский, братнин? – спросила она.
– Господский хлеб весь цел, – с гордостью сказал Дрон, – наш князь не приказывал продавать.
– Выдай его мужикам, выдай все, что им нужно: я тебе именем брата разрешаю, – сказала княжна Марья.
Дрон ничего не ответил и глубоко вздохнул.
– Ты раздай им этот хлеб, ежели его довольно будет для них. Все раздай. Я тебе приказываю именем брата, и скажи им: что, что наше, то и ихнее. Мы ничего не пожалеем для них. Так ты скажи.
Дрон пристально смотрел на княжну, в то время как она говорила.
– Уволь ты меня, матушка, ради бога, вели от меня ключи принять, – сказал он. – Служил двадцать три года, худого не делал; уволь, ради бога.
Княжна Марья не понимала, чего он хотел от нее и от чего он просил уволить себя. Она отвечала ему, что она никогда не сомневалась в его преданности и что она все готова сделать для него и для мужиков.


Через час после этого Дуняша пришла к княжне с известием, что пришел Дрон и все мужики, по приказанию княжны, собрались у амбара, желая переговорить с госпожою.
– Да я никогда не звала их, – сказала княжна Марья, – я только сказала Дронушке, чтобы раздать им хлеба.
– Только ради бога, княжна матушка, прикажите их прогнать и не ходите к ним. Все обман один, – говорила Дуняша, – а Яков Алпатыч приедут, и поедем… и вы не извольте…
– Какой же обман? – удивленно спросила княжна
– Да уж я знаю, только послушайте меня, ради бога. Вот и няню хоть спросите. Говорят, не согласны уезжать по вашему приказанию.
– Ты что нибудь не то говоришь. Да я никогда не приказывала уезжать… – сказала княжна Марья. – Позови Дронушку.
Пришедший Дрон подтвердил слова Дуняши: мужики пришли по приказанию княжны.
– Да я никогда не звала их, – сказала княжна. – Ты, верно, не так передал им. Я только сказала, чтобы ты им отдал хлеб.
Дрон, не отвечая, вздохнул.
– Если прикажете, они уйдут, – сказал он.
– Нет, нет, я пойду к ним, – сказала княжна Марья
Несмотря на отговариванье Дуняши и няни, княжна Марья вышла на крыльцо. Дрон, Дуняша, няня и Михаил Иваныч шли за нею. «Они, вероятно, думают, что я предлагаю им хлеб с тем, чтобы они остались на своих местах, и сама уеду, бросив их на произвол французов, – думала княжна Марья. – Я им буду обещать месячину в подмосковной, квартиры; я уверена, что Andre еще больше бы сделав на моем месте», – думала она, подходя в сумерках к толпе, стоявшей на выгоне у амбара.
Толпа, скучиваясь, зашевелилась, и быстро снялись шляпы. Княжна Марья, опустив глаза и путаясь ногами в платье, близко подошла к ним. Столько разнообразных старых и молодых глаз было устремлено на нее и столько было разных лиц, что княжна Марья не видала ни одного лица и, чувствуя необходимость говорить вдруг со всеми, не знала, как быть. Но опять сознание того, что она – представительница отца и брата, придало ей силы, и она смело начала свою речь.
– Я очень рада, что вы пришли, – начала княжна Марья, не поднимая глаз и чувствуя, как быстро и сильно билось ее сердце. – Мне Дронушка сказал, что вас разорила война. Это наше общее горе, и я ничего не пожалею, чтобы помочь вам. Я сама еду, потому что уже опасно здесь и неприятель близко… потому что… Я вам отдаю все, мои друзья, и прошу вас взять все, весь хлеб наш, чтобы у вас не было нужды. А ежели вам сказали, что я отдаю вам хлеб с тем, чтобы вы остались здесь, то это неправда. Я, напротив, прошу вас уезжать со всем вашим имуществом в нашу подмосковную, и там я беру на себя и обещаю вам, что вы не будете нуждаться. Вам дадут и домы и хлеба. – Княжна остановилась. В толпе только слышались вздохи.
– Я не от себя делаю это, – продолжала княжна, – я это делаю именем покойного отца, который был вам хорошим барином, и за брата, и его сына.
Она опять остановилась. Никто не прерывал ее молчания.
– Горе наше общее, и будем делить всё пополам. Все, что мое, то ваше, – сказала она, оглядывая лица, стоявшие перед нею.
Все глаза смотрели на нее с одинаковым выражением, значения которого она не могла понять. Было ли это любопытство, преданность, благодарность, или испуг и недоверие, но выражение на всех лицах было одинаковое.
– Много довольны вашей милостью, только нам брать господский хлеб не приходится, – сказал голос сзади.
– Да отчего же? – сказала княжна.
Никто не ответил, и княжна Марья, оглядываясь по толпе, замечала, что теперь все глаза, с которыми она встречалась, тотчас же опускались.
– Отчего же вы не хотите? – спросила она опять.
Никто не отвечал.
Княжне Марье становилось тяжело от этого молчанья; она старалась уловить чей нибудь взгляд.
– Отчего вы не говорите? – обратилась княжна к старому старику, который, облокотившись на палку, стоял перед ней. – Скажи, ежели ты думаешь, что еще что нибудь нужно. Я все сделаю, – сказала она, уловив его взгляд. Но он, как бы рассердившись за это, опустил совсем голову и проговорил:
– Чего соглашаться то, не нужно нам хлеба.
– Что ж, нам все бросить то? Не согласны. Не согласны… Нет нашего согласия. Мы тебя жалеем, а нашего согласия нет. Поезжай сама, одна… – раздалось в толпе с разных сторон. И опять на всех лицах этой толпы показалось одно и то же выражение, и теперь это было уже наверное не выражение любопытства и благодарности, а выражение озлобленной решительности.
– Да вы не поняли, верно, – с грустной улыбкой сказала княжна Марья. – Отчего вы не хотите ехать? Я обещаю поселить вас, кормить. А здесь неприятель разорит вас…
Но голос ее заглушали голоса толпы.
– Нет нашего согласия, пускай разоряет! Не берем твоего хлеба, нет согласия нашего!
Княжна Марья старалась уловить опять чей нибудь взгляд из толпы, но ни один взгляд не был устремлен на нее; глаза, очевидно, избегали ее. Ей стало странно и неловко.
– Вишь, научила ловко, за ней в крепость иди! Дома разори да в кабалу и ступай. Как же! Я хлеб, мол, отдам! – слышались голоса в толпе.
Княжна Марья, опустив голову, вышла из круга и пошла в дом. Повторив Дрону приказание о том, чтобы завтра были лошади для отъезда, она ушла в свою комнату и осталась одна с своими мыслями.


Долго эту ночь княжна Марья сидела у открытого окна в своей комнате, прислушиваясь к звукам говора мужиков, доносившегося с деревни, но она не думала о них. Она чувствовала, что, сколько бы она ни думала о них, она не могла бы понять их. Она думала все об одном – о своем горе, которое теперь, после перерыва, произведенного заботами о настоящем, уже сделалось для нее прошедшим. Она теперь уже могла вспоминать, могла плакать и могла молиться. С заходом солнца ветер затих. Ночь была тихая и свежая. В двенадцатом часу голоса стали затихать, пропел петух, из за лип стала выходить полная луна, поднялся свежий, белый туман роса, и над деревней и над домом воцарилась тишина.
Одна за другой представлялись ей картины близкого прошедшего – болезни и последних минут отца. И с грустной радостью она теперь останавливалась на этих образах, отгоняя от себя с ужасом только одно последнее представление его смерти, которое – она чувствовала – она была не в силах созерцать даже в своем воображении в этот тихий и таинственный час ночи. И картины эти представлялись ей с такой ясностью и с такими подробностями, что они казались ей то действительностью, то прошедшим, то будущим.
То ей живо представлялась та минута, когда с ним сделался удар и его из сада в Лысых Горах волокли под руки и он бормотал что то бессильным языком, дергал седыми бровями и беспокойно и робко смотрел на нее.
«Он и тогда хотел сказать мне то, что он сказал мне в день своей смерти, – думала она. – Он всегда думал то, что он сказал мне». И вот ей со всеми подробностями вспомнилась та ночь в Лысых Горах накануне сделавшегося с ним удара, когда княжна Марья, предчувствуя беду, против его воли осталась с ним. Она не спала и ночью на цыпочках сошла вниз и, подойдя к двери в цветочную, в которой в эту ночь ночевал ее отец, прислушалась к его голосу. Он измученным, усталым голосом говорил что то с Тихоном. Ему, видно, хотелось поговорить. «И отчего он не позвал меня? Отчего он не позволил быть мне тут на месте Тихона? – думала тогда и теперь княжна Марья. – Уж он не выскажет никогда никому теперь всего того, что было в его душе. Уж никогда не вернется для него и для меня эта минута, когда бы он говорил все, что ему хотелось высказать, а я, а не Тихон, слушала бы и понимала его. Отчего я не вошла тогда в комнату? – думала она. – Может быть, он тогда же бы сказал мне то, что он сказал в день смерти. Он и тогда в разговоре с Тихоном два раза спросил про меня. Ему хотелось меня видеть, а я стояла тут, за дверью. Ему было грустно, тяжело говорить с Тихоном, который не понимал его. Помню, как он заговорил с ним про Лизу, как живую, – он забыл, что она умерла, и Тихон напомнил ему, что ее уже нет, и он закричал: „Дурак“. Ему тяжело было. Я слышала из за двери, как он, кряхтя, лег на кровать и громко прокричал: „Бог мой!Отчего я не взошла тогда? Что ж бы он сделал мне? Что бы я потеряла? А может быть, тогда же он утешился бы, он сказал бы мне это слово“. И княжна Марья вслух произнесла то ласковое слово, которое он сказал ей в день смерти. «Ду ше нь ка! – повторила княжна Марья это слово и зарыдала облегчающими душу слезами. Она видела теперь перед собою его лицо. И не то лицо, которое она знала с тех пор, как себя помнила, и которое она всегда видела издалека; а то лицо – робкое и слабое, которое она в последний день, пригибаясь к его рту, чтобы слышать то, что он говорил, в первый раз рассмотрела вблизи со всеми его морщинами и подробностями.
«Душенька», – повторила она.
«Что он думал, когда сказал это слово? Что он думает теперь? – вдруг пришел ей вопрос, и в ответ на это она увидала его перед собой с тем выражением лица, которое у него было в гробу на обвязанном белым платком лице. И тот ужас, который охватил ее тогда, когда она прикоснулась к нему и убедилась, что это не только не был он, но что то таинственное и отталкивающее, охватил ее и теперь. Она хотела думать о другом, хотела молиться и ничего не могла сделать. Она большими открытыми глазами смотрела на лунный свет и тени, всякую секунду ждала увидеть его мертвое лицо и чувствовала, что тишина, стоявшая над домом и в доме, заковывала ее.
– Дуняша! – прошептала она. – Дуняша! – вскрикнула она диким голосом и, вырвавшись из тишины, побежала к девичьей, навстречу бегущим к ней няне и девушкам.


17 го августа Ростов и Ильин, сопутствуемые только что вернувшимся из плена Лаврушкой и вестовым гусаром, из своей стоянки Янково, в пятнадцати верстах от Богучарова, поехали кататься верхами – попробовать новую, купленную Ильиным лошадь и разузнать, нет ли в деревнях сена.
Богучарово находилось последние три дня между двумя неприятельскими армиями, так что так же легко мог зайти туда русский арьергард, как и французский авангард, и потому Ростов, как заботливый эскадронный командир, желал прежде французов воспользоваться тем провиантом, который оставался в Богучарове.
Ростов и Ильин были в самом веселом расположении духа. Дорогой в Богучарово, в княжеское именье с усадьбой, где они надеялись найти большую дворню и хорошеньких девушек, они то расспрашивали Лаврушку о Наполеоне и смеялись его рассказам, то перегонялись, пробуя лошадь Ильина.
Ростов и не знал и не думал, что эта деревня, в которую он ехал, была именье того самого Болконского, который был женихом его сестры.
Ростов с Ильиным в последний раз выпустили на перегонку лошадей в изволок перед Богучаровым, и Ростов, перегнавший Ильина, первый вскакал в улицу деревни Богучарова.
– Ты вперед взял, – говорил раскрасневшийся Ильин.
– Да, всё вперед, и на лугу вперед, и тут, – отвечал Ростов, поглаживая рукой своего взмылившегося донца.
– А я на французской, ваше сиятельство, – сзади говорил Лаврушка, называя французской свою упряжную клячу, – перегнал бы, да только срамить не хотел.
Они шагом подъехали к амбару, у которого стояла большая толпа мужиков.
Некоторые мужики сняли шапки, некоторые, не снимая шапок, смотрели на подъехавших. Два старые длинные мужика, с сморщенными лицами и редкими бородами, вышли из кабака и с улыбками, качаясь и распевая какую то нескладную песню, подошли к офицерам.
– Молодцы! – сказал, смеясь, Ростов. – Что, сено есть?
– И одинакие какие… – сказал Ильин.
– Развесе…oo…ооо…лая бесе… бесе… – распевали мужики с счастливыми улыбками.
Один мужик вышел из толпы и подошел к Ростову.
– Вы из каких будете? – спросил он.
– Французы, – отвечал, смеючись, Ильин. – Вот и Наполеон сам, – сказал он, указывая на Лаврушку.
– Стало быть, русские будете? – переспросил мужик.
– А много вашей силы тут? – спросил другой небольшой мужик, подходя к ним.
– Много, много, – отвечал Ростов. – Да вы что ж собрались тут? – прибавил он. – Праздник, что ль?
– Старички собрались, по мирскому делу, – отвечал мужик, отходя от него.
В это время по дороге от барского дома показались две женщины и человек в белой шляпе, шедшие к офицерам.
– В розовом моя, чур не отбивать! – сказал Ильин, заметив решительно подвигавшуюся к нему Дуняшу.
– Наша будет! – подмигнув, сказал Ильину Лаврушка.
– Что, моя красавица, нужно? – сказал Ильин, улыбаясь.
– Княжна приказали узнать, какого вы полка и ваши фамилии?
– Это граф Ростов, эскадронный командир, а я ваш покорный слуга.
– Бе…се…е…ду…шка! – распевал пьяный мужик, счастливо улыбаясь и глядя на Ильина, разговаривающего с девушкой. Вслед за Дуняшей подошел к Ростову Алпатыч, еще издали сняв свою шляпу.
– Осмелюсь обеспокоить, ваше благородие, – сказал он с почтительностью, но с относительным пренебрежением к юности этого офицера и заложив руку за пазуху. – Моя госпожа, дочь скончавшегося сего пятнадцатого числа генерал аншефа князя Николая Андреевича Болконского, находясь в затруднении по случаю невежества этих лиц, – он указал на мужиков, – просит вас пожаловать… не угодно ли будет, – с грустной улыбкой сказал Алпатыч, – отъехать несколько, а то не так удобно при… – Алпатыч указал на двух мужиков, которые сзади так и носились около него, как слепни около лошади.
– А!.. Алпатыч… А? Яков Алпатыч!.. Важно! прости ради Христа. Важно! А?.. – говорили мужики, радостно улыбаясь ему. Ростов посмотрел на пьяных стариков и улыбнулся.
– Или, может, это утешает ваше сиятельство? – сказал Яков Алпатыч с степенным видом, не заложенной за пазуху рукой указывая на стариков.
– Нет, тут утешенья мало, – сказал Ростов и отъехал. – В чем дело? – спросил он.
– Осмелюсь доложить вашему сиятельству, что грубый народ здешний не желает выпустить госпожу из имения и угрожает отпречь лошадей, так что с утра все уложено и ее сиятельство не могут выехать.
– Не может быть! – вскрикнул Ростов.
– Имею честь докладывать вам сущую правду, – повторил Алпатыч.
Ростов слез с лошади и, передав ее вестовому, пошел с Алпатычем к дому, расспрашивая его о подробностях дела. Действительно, вчерашнее предложение княжны мужикам хлеба, ее объяснение с Дроном и с сходкою так испортили дело, что Дрон окончательно сдал ключи, присоединился к мужикам и не являлся по требованию Алпатыча и что поутру, когда княжна велела закладывать, чтобы ехать, мужики вышли большой толпой к амбару и выслали сказать, что они не выпустят княжны из деревни, что есть приказ, чтобы не вывозиться, и они выпрягут лошадей. Алпатыч выходил к ним, усовещивая их, но ему отвечали (больше всех говорил Карп; Дрон не показывался из толпы), что княжну нельзя выпустить, что на то приказ есть; а что пускай княжна остается, и они по старому будут служить ей и во всем повиноваться.
В ту минуту, когда Ростов и Ильин проскакали по дороге, княжна Марья, несмотря на отговариванье Алпатыча, няни и девушек, велела закладывать и хотела ехать; но, увидав проскакавших кавалеристов, их приняли за французов, кучера разбежались, и в доме поднялся плач женщин.
– Батюшка! отец родной! бог тебя послал, – говорили умиленные голоса, в то время как Ростов проходил через переднюю.
Княжна Марья, потерянная и бессильная, сидела в зале, в то время как к ней ввели Ростова. Она не понимала, кто он, и зачем он, и что с нею будет. Увидав его русское лицо и по входу его и первым сказанным словам признав его за человека своего круга, она взглянула на него своим глубоким и лучистым взглядом и начала говорить обрывавшимся и дрожавшим от волнения голосом. Ростову тотчас же представилось что то романическое в этой встрече. «Беззащитная, убитая горем девушка, одна, оставленная на произвол грубых, бунтующих мужиков! И какая то странная судьба натолкнула меня сюда! – думал Ростов, слушяя ее и глядя на нее. – И какая кротость, благородство в ее чертах и в выражении! – думал он, слушая ее робкий рассказ.
Когда она заговорила о том, что все это случилось на другой день после похорон отца, ее голос задрожал. Она отвернулась и потом, как бы боясь, чтобы Ростов не принял ее слова за желание разжалобить его, вопросительно испуганно взглянула на него. У Ростова слезы стояли в глазах. Княжна Марья заметила это и благодарно посмотрела на Ростова тем своим лучистым взглядом, который заставлял забывать некрасивость ее лица.
– Не могу выразить, княжна, как я счастлив тем, что я случайно заехал сюда и буду в состоянии показать вам свою готовность, – сказал Ростов, вставая. – Извольте ехать, и я отвечаю вам своей честью, что ни один человек не посмеет сделать вам неприятность, ежели вы мне только позволите конвоировать вас, – и, почтительно поклонившись, как кланяются дамам царской крови, он направился к двери.
Почтительностью своего тона Ростов как будто показывал, что, несмотря на то, что он за счастье бы счел свое знакомство с нею, он не хотел пользоваться случаем ее несчастия для сближения с нею.
Княжна Марья поняла и оценила этот тон.
– Я очень, очень благодарна вам, – сказала ему княжна по французски, – но надеюсь, что все это было только недоразуменье и что никто не виноват в том. – Княжна вдруг заплакала. – Извините меня, – сказала она.
Ростов, нахмурившись, еще раз низко поклонился и вышел из комнаты.


– Ну что, мила? Нет, брат, розовая моя прелесть, и Дуняшей зовут… – Но, взглянув на лицо Ростова, Ильин замолк. Он видел, что его герой и командир находился совсем в другом строе мыслей.
Ростов злобно оглянулся на Ильина и, не отвечая ему, быстрыми шагами направился к деревне.
– Я им покажу, я им задам, разбойникам! – говорил он про себя.
Алпатыч плывущим шагом, чтобы только не бежать, рысью едва догнал Ростова.
– Какое решение изволили принять? – сказал он, догнав его.
Ростов остановился и, сжав кулаки, вдруг грозно подвинулся на Алпатыча.
– Решенье? Какое решенье? Старый хрыч! – крикнул он на него. – Ты чего смотрел? А? Мужики бунтуют, а ты не умеешь справиться? Ты сам изменник. Знаю я вас, шкуру спущу со всех… – И, как будто боясь растратить понапрасну запас своей горячности, он оставил Алпатыча и быстро пошел вперед. Алпатыч, подавив чувство оскорбления, плывущим шагом поспевал за Ростовым и продолжал сообщать ему свои соображения. Он говорил, что мужики находились в закоснелости, что в настоящую минуту было неблагоразумно противуборствовать им, не имея военной команды, что не лучше ли бы было послать прежде за командой.